teamix-evo 0.9.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -30
- package/dist/core/index.d.ts +44 -221
- package/dist/core/index.js +636 -1873
- package/dist/core/index.js.map +1 -1
- package/dist/index.js +6936 -6106
- package/dist/index.js.map +1 -1
- package/package.json +17 -17
- package/LICENSE +0 -21
package/dist/core/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/tokens-init.ts","../../src/utils/fs.ts","../../src/utils/logger.ts","../../src/utils/hash.ts","../../src/core/state.ts","../../src/utils/error.ts","../../src/core/skills-client.ts","../../src/core/skills-installer.ts","../../src/ide/QoderAdapter.ts","../../src/ide/ClaudeAdapter.ts","../../src/ide/index.ts","../../src/utils/template.ts","../../src/utils/path.ts","../../src/utils/mcp.ts","../../src/core/skills-add.ts","../../src/core/skills-update.ts","../../src/core/ui-init.ts","../../src/core/ui-client.ts","../../src/core/ui-installer.ts","../../src/utils/transform-imports.ts","../../src/core/ui-add.ts","../../src/core/ui-list.ts","../../src/core/variant-ui-add.ts","../../src/core/lint-init.ts","../../src/core/agents-md.ts","../../src/core/init-detect.ts","../../src/core/init-conflicts.ts","../../src/core/legacy-tokens-migrate.ts","../../src/core/snapshot.ts","../../src/core/file-changes.ts","../../src/core/project-init.ts","../../src/core/project-update.ts","../../src/core/tokens-update.ts","../../src/core/upgrade-hints.ts","../../src/core/managed-merge.ts","../../src/core/ui-upgrade-detector.ts","../../src/core/ui-upgrade.ts","../../src/core/ui-upgrade-staging.ts","../../src/core/installer.ts","../../src/core/registry-client.ts"],"sourcesContent":["/**\n * Programmatic tokens init — installs one variant's token files into the\n * consumer's project root `tokens/` directory.\n *\n * Per [ADR 0020](../../../../docs/adr/0020-design-to-tokens-skill-fusion.md)\n * the install model is now a flat copy: each variant in `@teamix-evo/tokens`\n * advertises its files in the package manifest; for each advertised file we\n * copy by basename into `<projectRoot>/tokens/`:\n *\n * variants/<variant>/theme.css → tokens/tokens.theme.css (regenerable)\n * variants/<variant>/base.tokens.json → (kept in package only — reference data)\n *\n * Plus we always ensure `tokens/tokens.overrides.css` exists at the consumer\n * (created empty if absent, frozen thereafter so user edits are preserved\n * across re-installs).\n *\n * No walk-and-merge, no `default` baseline — every variant is a\n * self-contained token set per ADR 0020 §3.\n */\nimport * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport {\n loadTokensPackageManifest,\n getVariantEntry,\n type TokensPackLock,\n type InstalledManifest,\n type InstalledResource,\n type ProjectConfig,\n type UpdateStrategy,\n} from '@teamix-evo/registry';\nimport { backupFile, writeFileSafe, fileExists } from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport {\n ensureTeamixDir,\n readProjectConfig,\n writeProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\nimport { runSkillsAdd } from './skills-add.js';\nimport { ensureMcpJson } from '../utils/mcp.js';\nimport { loadSkillsData } from './skills-client.js';\nimport { logger } from '../utils/logger.js';\nimport type { SkillIde, SkillScope } from '@teamix-evo/registry';\nimport { resolveTokensPackageRoot } from '../utils/path.js';\nimport { getErrorMessage } from '../utils/error.js';\n\nconst DEFAULT_SKILLS_PACKAGE = '@teamix-evo/skills';\nconst DEFAULT_AUTO_SKILL_IDES: SkillIde[] = ['qoder', 'claude'];\nconst DEFAULT_AUTO_SKILL_SCOPE: SkillScope = 'project';\n\nconst DEFAULT_TOKENS_PACKAGE = '@teamix-evo/tokens';\n\n/** Consumer-side directory where token files land. */\nconst CONSUMER_TOKENS_DIR = 'tokens';\n\n/** Consumer-side filename for the regenerable theme. */\nconst CONSUMER_THEME_FILE = 'tokens.theme.css';\n\n/** Consumer-side filename for the frozen user-owned override. */\nconst CONSUMER_OVERRIDES_FILE = 'tokens.overrides.css';\n\n/** Default empty content for a fresh `tokens.overrides.css`. */\nconst EMPTY_OVERRIDES_TEMPLATE = `/* User-owned token overrides — frozen on subsequent installs. */\n/* See @teamix-evo/tokens variant theme.css for available CSS custom properties. */\n`;\n\nexport interface RunTokensInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Tokens variant id (e.g. `\"opentrek\"`, `\"uni-manager\"`). */\n variant: string;\n /** IDE identifier written into config.json (e.g. `\"qoder\"`, `\"claude\"`). */\n ide: string;\n /** Override the tokens package name (defaults to `\"@teamix-evo/tokens\"`). */\n packageName?: string;\n /**\n * Override resolution of the tokens package root. When provided, skips\n * `require.resolve(\"<packageName>/package.json\")`. Useful for tests that\n * want to point at a fixture tree, and for embedding inside `create`\n * where the package may not yet be installed in the consumer.\n */\n packageRoot?: string;\n}\n\n/**\n * Outcome of the post-init skill auto-install step. `attempted` is the variant\n * skill id we tried to install; `addedSkillIds` is what was actually installed\n * (empty if the skill was already present); `missing` lists ids that aren't in\n * the manifest (warned, not fatal). Per ADR / \"skills self-contained\" decision,\n * each variant skill is fully self-contained — no separate baseline skill.\n */\nexport interface SkillsAutoInstallResult {\n attempted: string[];\n addedSkillIds: string[];\n skippedSkillIds: string[];\n missing: string[];\n}\n\nexport type RunTokensInitResult =\n | {\n status: 'installed';\n packageName: string;\n variant: string;\n version: string;\n count: number;\n resources: InstalledResource[];\n /** Result of the auto-install of the matching design skill. */\n skills?: SkillsAutoInstallResult;\n }\n | {\n status: 'already-initialized';\n existingVariant: string;\n }\n | {\n status: 'variant-mismatch';\n existingVariant: string;\n requestedVariant: string;\n };\n\n/**\n * Programmatic equivalent of `teamix-evo tokens init <variant>`.\n *\n * Side effects:\n * - Creates `<projectRoot>/.teamix-evo/`\n * - Copies the variant's `theme.css` to `<projectRoot>/tokens/tokens.theme.css`\n * - Ensures `<projectRoot>/tokens/tokens.overrides.css` exists (frozen)\n * - Writes `tokens-lock.json`, `config.json`, `manifest.json` (installed)\n *\n * No interactive prompts, no `process.exit`. Throws on hard failure (P8).\n */\nexport async function runTokensInit(\n options: RunTokensInitOptions,\n): Promise<RunTokensInitResult> {\n const { projectRoot, variant, ide } = options;\n const packageName = options.packageName ?? DEFAULT_TOKENS_PACKAGE;\n\n await ensureTeamixDir(projectRoot);\n\n // Resolve the catalog up front so variant-name validation runs before any\n // state-driven branching (#P2-3). An unknown variant should produce a\n // clear \"Unknown variant\" error regardless of whether tokens are already\n // installed for the project.\n const packageRoot =\n options.packageRoot ?? resolveTokensPackageRoot(packageName);\n const catalog = await loadTokensPackageManifest(packageRoot);\n const variantEntry = getVariantEntry(catalog, variant);\n if (!variantEntry) {\n const known = catalog.variants.map((v) => v.name).join(', ');\n throw new Error(\n `Unknown variant \"${variant}\". Available variants: ${\n known || '(none)'\n }.\\nRun \\`npx teamix-evo@latest tokens list-variants\\` to see all options.`,\n );\n }\n\n // Variant-switching guard: if a different variant is already installed,\n // require the user to explicitly uninstall first (#15). Same-variant re-init\n // is a no-op (already-initialized).\n const existingConfig = await readProjectConfig(projectRoot);\n if (existingConfig?.packages?.tokens) {\n const existingVariant = existingConfig.packages.tokens.variant;\n if (existingVariant === variant) {\n return { status: 'already-initialized', existingVariant };\n }\n return {\n status: 'variant-mismatch',\n existingVariant,\n requestedVariant: variant,\n };\n }\n\n // Install advertised files by basename → consumer tokens/ directory.\n const installed: InstalledResource[] = [];\n for (const fileRel of variantEntry.files) {\n const result = await installVariantFile(fileRel, packageRoot, projectRoot);\n if (result) installed.push(result);\n }\n\n // Always ensure the user-owned overrides file exists (frozen).\n const overridesAbs = path.join(\n projectRoot,\n CONSUMER_TOKENS_DIR,\n CONSUMER_OVERRIDES_FILE,\n );\n if (!(await fileExists(overridesAbs))) {\n await writeFileSafe(overridesAbs, EMPTY_OVERRIDES_TEMPLATE);\n }\n const overridesContent = await fs.readFile(overridesAbs, 'utf-8');\n installed.push({\n id: `tokens:${CONSUMER_OVERRIDES_FILE}`,\n target: path.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_OVERRIDES_FILE),\n hash: computeHash(overridesContent),\n strategy: 'frozen',\n });\n\n // Write consumer-side state files.\n const lock: TokensPackLock = {\n schemaVersion: 1,\n variant: {\n name: variantEntry.name,\n displayName: variantEntry.displayName,\n version: variantEntry.version,\n from: packageName,\n },\n packageVersion: catalog.version,\n linked: variantEntry.linked,\n installedAt: new Date().toISOString(),\n };\n await writeFileSafe(\n path.join(projectRoot, '.teamix-evo', 'tokens-lock.json'),\n JSON.stringify(lock, null, 2) + '\\n',\n );\n\n // Merge into existing config so unrelated package entries (skills / ui)\n // aren't clobbered (#18).\n const config: ProjectConfig = {\n $schema: 'https://teamix-evo.dev/schema/config/v2.json',\n schemaVersion: 2,\n ide: existingConfig?.ide ?? ide,\n packages: {\n ...(existingConfig?.packages ?? {}),\n tokens: {\n variant,\n version: variantEntry.version,\n tailwind: 'v4',\n },\n },\n };\n await writeProjectConfig(projectRoot, config);\n\n // Merge into existing installed manifest so other packages (ui / biz-ui /\n // templates) recorded earlier are preserved.\n const prior = (await readInstalledManifest(projectRoot)) ?? {\n schemaVersion: 1 as const,\n installed: [],\n };\n const tokensIdx = prior.installed.findIndex((p) => p.package === packageName);\n const tokensEntry = {\n package: packageName,\n variant,\n version: variantEntry.version,\n installedAt: new Date().toISOString(),\n resources: installed,\n };\n if (tokensIdx >= 0) prior.installed[tokensIdx] = tokensEntry;\n else prior.installed.push(tokensEntry);\n await writeInstalledManifest(projectRoot, prior);\n\n // Ensure `.mcp.json` exists for incremental adopters (#BUG-103). Done\n // before the auto-skills install so even if the latter fails the MCP\n // wiring is in place.\n await ensureMcpJson(projectRoot);\n\n // After the lock + manifest are persisted, auto-install matching skills.\n // Failures here do NOT roll back the install — the skill layer is additive,\n // and the user can always re-run `skills init` (bulk) or `skills add <id>`\n // (incremental) manually.\n const skills = await tryAutoInstallVariantSkills({\n projectRoot,\n variant,\n ide,\n });\n\n return {\n status: 'installed',\n packageName,\n variant,\n version: variantEntry.version,\n count: installed.length,\n resources: installed,\n skills,\n };\n}\n\n/**\n * Auto-install the variant skill `teamix-evo-design-<variant>` (if present\n * in the skills manifest). Each variant skill is fully self-contained — no\n * separate baseline. A missing variant skill produces a warning, not a failure.\n */\nasync function tryAutoInstallVariantSkills(args: {\n projectRoot: string;\n variant: string;\n ide: string;\n}): Promise<SkillsAutoInstallResult> {\n const { projectRoot, variant, ide } = args;\n const variantSkillId = `teamix-evo-design-${variant}`;\n const desired = [variantSkillId];\n\n // Filter to skills actually present in the manifest. Anything missing\n // becomes a warning but is not fatal.\n let manifestSkillIds: Set<string>;\n try {\n const { manifest } = await loadSkillsData(DEFAULT_SKILLS_PACKAGE);\n manifestSkillIds = new Set(manifest.skills.map((s) => s.id));\n } catch (err) {\n logger.warn(\n `Skipping skills auto-install: could not load skills manifest (${getErrorMessage(\n err,\n )}).`,\n );\n return {\n attempted: [],\n addedSkillIds: [],\n skippedSkillIds: [],\n missing: desired,\n };\n }\n\n const present = desired.filter((id) => manifestSkillIds.has(id));\n const missing = desired.filter((id) => !manifestSkillIds.has(id));\n if (missing.length > 0) {\n logger.warn(\n `Skills auto-install: not found in manifest, skipping: ${missing.join(\n ', ',\n )}.`,\n );\n }\n if (present.length === 0) {\n return {\n attempted: desired,\n addedSkillIds: [],\n skippedSkillIds: [],\n missing,\n };\n }\n\n try {\n const result = await runSkillsAdd({\n projectRoot,\n names: present,\n ides: DEFAULT_AUTO_SKILL_IDES,\n scope: DEFAULT_AUTO_SKILL_SCOPE,\n ide,\n });\n if (result.status !== 'installed') {\n return {\n attempted: desired,\n addedSkillIds: [],\n skippedSkillIds: present,\n missing,\n };\n }\n return {\n attempted: desired,\n addedSkillIds: result.addedSkillIds,\n skippedSkillIds: result.skippedSkillIds,\n missing,\n };\n } catch (err) {\n logger.warn(\n `Skills auto-install failed (continuing): ${getErrorMessage(err)}`,\n );\n return {\n attempted: desired,\n addedSkillIds: [],\n skippedSkillIds: [],\n missing,\n };\n }\n}\n\n/**\n * Install one advertised variant file. Mapping by basename:\n *\n * theme.css → consumer `tokens/tokens.theme.css` (regenerable)\n * overrides.css → consumer `tokens/tokens.overrides.css` (frozen, see runTokensInit)\n * anything else → skipped (reference data — kept in npm package only)\n *\n * The `overrides.css` source file is rare today (variants don't ship one),\n * but the mapping is here so authors can opt in. The \"always-create\" path in\n * `runTokensInit` covers the normal case where no source override is present.\n */\nasync function installVariantFile(\n fileRelToPackage: string,\n packageRoot: string,\n projectRoot: string,\n): Promise<InstalledResource | null> {\n const sourceAbs = path.join(packageRoot, fileRelToPackage);\n const base = path.basename(fileRelToPackage);\n\n if (base === 'theme.css') {\n const targetRel = path.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_THEME_FILE);\n const targetAbs = path.join(projectRoot, targetRel);\n const content = await fs.readFile(sourceAbs, 'utf-8');\n // Phase 1.A2: theme.css is regenerable but users sometimes hand-edit it.\n // Stash any pre-existing copy under .teamix-evo/.backups/ before we\n // overwrite so a stale-state recovery is always possible.\n if (await fileExists(targetAbs)) {\n await backupFile(targetAbs, projectRoot);\n }\n await writeFileSafe(targetAbs, content);\n return {\n id: `tokens:${CONSUMER_THEME_FILE}`,\n target: targetRel,\n hash: computeHash(content),\n strategy: 'regenerable',\n };\n }\n\n if (base === 'overrides.css' || base === 'tokens.overrides.css') {\n const targetRel = path.posix.join(\n CONSUMER_TOKENS_DIR,\n CONSUMER_OVERRIDES_FILE,\n );\n const targetAbs = path.join(projectRoot, targetRel);\n if (await fileExists(targetAbs)) {\n // Frozen — leave the user's customization alone.\n const existing = await fs.readFile(targetAbs, 'utf-8');\n return {\n id: `tokens:${CONSUMER_OVERRIDES_FILE}`,\n target: targetRel,\n hash: computeHash(existing),\n strategy: 'frozen',\n };\n }\n const content = await fs.readFile(sourceAbs, 'utf-8');\n await writeFileSafe(targetAbs, content);\n return {\n id: `tokens:${CONSUMER_OVERRIDES_FILE}`,\n target: targetRel,\n hash: computeHash(content),\n strategy: 'frozen',\n };\n }\n\n // Reference data (e.g. base.tokens.json) — kept in the npm package only.\n return null;\n}\n\n/**\n * List all variants advertised by the top-level tokens catalog. Used by\n * `teamix-evo tokens list-variants`.\n */\nexport interface ListVariantsResult {\n packageName: string;\n packageVersion: string;\n variants: Array<{\n name: string;\n displayName: string;\n version: string;\n description?: string;\n linked?: { 'biz-ui'?: string; templates?: string };\n }>;\n}\n\nexport async function listTokenVariants(\n packageName: string = DEFAULT_TOKENS_PACKAGE,\n packageRoot?: string,\n): Promise<ListVariantsResult> {\n const root = packageRoot ?? resolveTokensPackageRoot(packageName);\n const catalog = await loadTokensPackageManifest(root);\n return {\n packageName,\n packageVersion: catalog.version,\n variants: catalog.variants.map((v) => ({\n name: v.name,\n displayName: v.displayName,\n version: v.version,\n description: v.description,\n linked: v.linked,\n })),\n };\n}\n\n// Re-export the strategy enum constituents so consumers don't have to import\n// from registry separately.\nexport type { UpdateStrategy };\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Recursively create a directory (like mkdir -p).\n */\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\n/**\n * Atomic write: write to a .tmp file first, then rename.\n */\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n): Promise<void> {\n const dir = path.dirname(filePath);\n await ensureDir(dir);\n const tmp = filePath + \".tmp\";\n await fs.writeFile(tmp, content, \"utf-8\");\n await fs.rename(tmp, filePath);\n}\n\n/**\n * Read a file or return null if it doesn't exist.\n */\nexport async function readFileOrNull(\n filePath: string,\n): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Create a backup of a file under `.teamix-evo/.backups/`.\n */\nexport async function backupFile(\n filePath: string,\n projectRoot: string,\n): Promise<void> {\n const content = await readFileOrNull(filePath);\n if (content === null) {\n logger.debug(`Skip backup: ${filePath} does not exist`);\n return;\n }\n\n const rel = path.relative(projectRoot, filePath);\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const backupPath = path.join(\n projectRoot,\n \".teamix-evo\",\n \".backups\",\n `${rel}.${timestamp}.bak`,\n );\n\n await ensureDir(path.dirname(backupPath));\n await fs.writeFile(backupPath, content, \"utf-8\");\n logger.debug(`Backed up ${rel} → ${path.relative(projectRoot, backupPath)}`);\n}\n\n/**\n * Check whether a file exists.\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","import { red, yellow, cyan, green, gray } from \"kolorist\";\n\nconst isDebug = process.env.TEAMIX_DEBUG === \"1\";\n\nexport const logger = {\n info(msg: string): void {\n console.log(cyan(\"ℹ\"), msg);\n },\n\n warn(msg: string): void {\n console.warn(yellow(\"⚠\"), msg);\n },\n\n error(msg: string): void {\n console.error(red(\"✖\"), msg);\n },\n\n success(msg: string): void {\n console.log(green(\"✔\"), msg);\n },\n\n debug(msg: string): void {\n if (isDebug) {\n console.log(gray(\"⊡\"), gray(msg));\n }\n },\n};\n","import { createHash } from \"node:crypto\";\n\n/**\n * Compute a SHA-256 hash of the given content.\n * Returns a string in the format \"sha256:<hex>\".\n */\nexport function computeHash(content: string): string {\n const hash = createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n return `sha256:${hash}`;\n}\n","import * as path from 'node:path';\nimport type {\n ProjectConfig,\n InstalledManifest,\n InstalledPackage,\n SkillsLock,\n TokensPackLock,\n} from '@teamix-evo/registry';\nimport {\n validateConfig,\n validateInstalled,\n validateSkillsLock,\n TokensPackLockSchema,\n} from '@teamix-evo/registry';\nimport { readFileOrNull, writeFileSafe, ensureDir } from '../utils/fs.js';\nimport { getErrorMessage } from '../utils/error.js';\nimport { logger } from '../utils/logger.js';\n\nconst TEAMIX_DIR = '.teamix-evo';\nconst CONFIG_FILE = 'config.json';\nconst MANIFEST_FILE = 'manifest.json';\nconst TOKENS_LOCK_FILE = 'tokens-lock.json';\n/**\n * Consumer-side directory under `.teamix-evo/` that holds the skill source\n * mirrors (per ADR 0013). Renamed from `skills` → `skills-source` in the Init\n * landing improvement plan to avoid name-clash with installed package roots\n * and IDE mirror buckets; legacy paths are migrated lazily via\n * `migrateLegacySkillsSourceDir` (see `skills-installer.ts`).\n */\nconst SKILLS_DIR = 'skills-source';\n/** Legacy directory name retained for one-shot migration detection. */\nexport const LEGACY_SKILLS_DIR = 'skills';\nconst SKILLS_LOCK_FILE = 'manifest.lock.json';\n\n/**\n * Get the .teamix-evo directory path for a project.\n */\nexport function getTeamixDir(projectRoot: string): string {\n return path.join(projectRoot, TEAMIX_DIR);\n}\n\n/**\n * Ensure the .teamix-evo directory exists.\n */\nexport async function ensureTeamixDir(projectRoot: string): Promise<string> {\n const dir = getTeamixDir(projectRoot);\n await ensureDir(dir);\n return dir;\n}\n\n/**\n * Read the project config from .teamix-evo/config.json.\n * Returns null if the file does not exist; THROWS on corrupted content\n * so callers don't silently clobber prior config (#32 #18).\n */\nexport async function readProjectConfig(\n projectRoot: string,\n): Promise<ProjectConfig | null> {\n const configPath = path.join(projectRoot, TEAMIX_DIR, CONFIG_FILE);\n const raw = await readFileOrNull(configPath);\n if (raw === null) return null;\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `Corrupted config.json (${getErrorMessage(err)}). ` +\n `Fix the JSON manually or remove the file to start fresh; refusing to clobber prior config.`,\n );\n }\n const result = validateConfig(data);\n if (!result.success) {\n throw new Error(\n `Invalid config.json schema: ${result.error}. ` +\n `Fix the file manually or remove it to start fresh.`,\n );\n }\n return result.data;\n}\n\n/**\n * Write the project config to .teamix-evo/config.json.\n */\nexport async function writeProjectConfig(\n projectRoot: string,\n config: ProjectConfig,\n): Promise<void> {\n const configPath = path.join(projectRoot, TEAMIX_DIR, CONFIG_FILE);\n await writeFileSafe(configPath, JSON.stringify(config, null, 2) + '\\n');\n logger.debug(`Wrote config → ${configPath}`);\n}\n\n/**\n * Read the installed manifest from .teamix-evo/manifest.json.\n * Returns null if the file does not exist; THROWS on corrupted content so\n * callers don't silently lose prior installs by treating broken JSON as\n * \"fresh install\" (#32 #18). Use `readInstalledManifestOrNull` for the\n * old lenient behavior.\n */\nexport async function readInstalledManifest(\n projectRoot: string,\n): Promise<InstalledManifest | null> {\n const manifestPath = path.join(projectRoot, TEAMIX_DIR, MANIFEST_FILE);\n const raw = await readFileOrNull(manifestPath);\n if (raw === null) return null;\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `Corrupted manifest.json (${getErrorMessage(err)}). ` +\n `Fix the JSON manually or remove the file to start fresh; refusing to clobber prior install records.`,\n );\n }\n const result = validateInstalled(data);\n if (!result.success) {\n throw new Error(\n `Invalid manifest.json schema: ${result.error}. ` +\n `Fix the file manually or remove it to start fresh.`,\n );\n }\n return result.data;\n}\n\n/**\n * Write the installed manifest to .teamix-evo/manifest.json.\n */\nexport async function writeInstalledManifest(\n projectRoot: string,\n manifest: InstalledManifest,\n): Promise<void> {\n const manifestPath = path.join(projectRoot, TEAMIX_DIR, MANIFEST_FILE);\n await writeFileSafe(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n logger.debug(`Wrote manifest → ${manifestPath}`);\n}\n\n/**\n * Read .teamix-evo/tokens-lock.json. Returns null if missing or invalid.\n */\nexport async function readTokensLock(\n projectRoot: string,\n): Promise<TokensPackLock | null> {\n const lockPath = path.join(projectRoot, TEAMIX_DIR, TOKENS_LOCK_FILE);\n const raw = await readFileOrNull(lockPath);\n if (raw === null) return null;\n try {\n const parsed = TokensPackLockSchema.safeParse(JSON.parse(raw));\n if (!parsed.success) {\n logger.warn(`Invalid tokens-lock.json: ${parsed.error.message}`);\n return null;\n }\n return parsed.data;\n } catch (err) {\n logger.warn(`Failed to parse tokens-lock.json: ${getErrorMessage(err)}`);\n return null;\n }\n}\n\n/**\n * Convenience: read just the variant id from tokens-lock.json. Returns null\n * when no tokens variant has been installed.\n */\nexport async function readTokensVariant(\n projectRoot: string,\n): Promise<string | null> {\n const lock = await readTokensLock(projectRoot);\n return lock?.variant.name ?? null;\n}\n\n/**\n * Absolute path to the per-skill source directory (consumer-side source).\n * Per ADR 0013, this is the truth source from which IDE mirrors are produced.\n * Resolves under `<projectRoot>/.teamix-evo/skills-source/[<skillName>]`.\n */\nexport function getSkillsSourceDir(\n projectRoot: string,\n skillName?: string,\n): string {\n const base = path.join(projectRoot, TEAMIX_DIR, SKILLS_DIR);\n return skillName ? path.join(base, skillName) : base;\n}\n\n/**\n * Absolute path to the legacy `<projectRoot>/.teamix-evo/skills/` directory.\n * Used **only** by the lazy migration path; do not write into this location.\n */\nexport function getLegacySkillsSourceDir(projectRoot: string): string {\n return path.join(projectRoot, TEAMIX_DIR, LEGACY_SKILLS_DIR);\n}\n\n/**\n * Read .teamix-evo/skills/manifest.lock.json. Returns null if missing.\n */\nexport async function readSkillsLock(\n projectRoot: string,\n): Promise<SkillsLock | null> {\n const lockPath = path.join(\n projectRoot,\n TEAMIX_DIR,\n SKILLS_DIR,\n SKILLS_LOCK_FILE,\n );\n const raw = await readFileOrNull(lockPath);\n if (raw === null) return null;\n try {\n const data = JSON.parse(raw);\n const result = validateSkillsLock(data);\n if (!result.success) {\n logger.warn(`Invalid skills manifest.lock.json: ${result.error}`);\n return null;\n }\n return result.data;\n } catch (err) {\n logger.warn(\n `Failed to parse skills manifest.lock.json: ${getErrorMessage(err)}`,\n );\n return null;\n }\n}\n\n/**\n * Write .teamix-evo/skills/manifest.lock.json.\n */\nexport async function writeSkillsLock(\n projectRoot: string,\n lock: SkillsLock,\n): Promise<void> {\n const lockPath = path.join(\n projectRoot,\n TEAMIX_DIR,\n SKILLS_DIR,\n SKILLS_LOCK_FILE,\n );\n await writeFileSafe(lockPath, JSON.stringify(lock, null, 2) + '\\n');\n logger.debug(`Wrote skills lock → ${lockPath}`);\n}\n\n/**\n * Look up an installed package record by package name.\n *\n * The {@link InstalledManifest} schema does not enforce uniqueness on the\n * `package` key — variant switches re-append a new record rather than\n * mutating the old one. We therefore return the **last** match (chronological\n * latest) and `null` when no record exists.\n *\n * Shared helper consumed by both {@link ui-upgrade-detector} and\n * {@link ui-upgrade-staging} to keep the lookup semantics aligned.\n */\nexport function findInstalledPackage(\n installed: InstalledManifest | null,\n packageName: string,\n): InstalledPackage | null {\n if (!installed) return null;\n const matches = installed.installed.filter((p) => p.package === packageName);\n if (matches.length === 0) return null;\n return matches[matches.length - 1] ?? null;\n}\n","/**\n * Safely extract an error message from an unknown thrown value.\n *\n * JavaScript allows `throw \"string\"` / `throw 42` / `throw null` — using\n * `(err as Error).message` directly is unsafe. This normaliser covers all\n * runtime cases.\n */\nexport function getErrorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n if (typeof err === 'string') return err;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport type { SkillsPackageManifest } from '@teamix-evo/registry';\nimport { loadSkillsPackageManifest } from '@teamix-evo/registry';\nimport { logger } from '../utils/logger.js';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Resolve the package root directory for the skills package.\n */\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\n/**\n * Load the skills package manifest and optional shared `_data.json`.\n *\n * @param packageName - e.g. \"@teamix-evo/skills\"\n */\nexport async function loadSkillsData(packageName: string): Promise<{\n manifest: SkillsPackageManifest;\n data: Record<string, unknown>;\n packageRoot: string;\n}> {\n const packageRoot = resolvePackageRoot(packageName);\n\n logger.debug(`Resolved skills package root: ${packageRoot}`);\n\n const manifest = await loadSkillsPackageManifest(packageRoot);\n\n let data: Record<string, unknown> = {};\n const dataPath = path.join(packageRoot, '_data.json');\n try {\n const raw = await fs.readFile(dataPath, 'utf-8');\n data = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err;\n }\n logger.debug(`No _data.json found at ${dataPath}, using empty data`);\n }\n\n return { manifest, data, packageRoot };\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport type {\n SkillEntry,\n SkillsPackageManifest,\n InstalledResource,\n SkillIde,\n SkillScope,\n} from '@teamix-evo/registry';\nimport {\n replaceManagedRegion,\n hasManagedRegion,\n extractFrontmatter,\n replaceFrontmatter,\n} from '@teamix-evo/registry';\nimport { getAdapter } from '../ide/index.js';\nimport {\n writeFileSafe,\n readFileOrNull,\n fileExists,\n ensureDir,\n backupFile,\n} from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport { renderTemplate, loadTemplateFile } from '../utils/template.js';\nimport { logger } from '../utils/logger.js';\nimport { getErrorMessage } from '../utils/error.js';\nimport { walkDir } from '../utils/path.js';\nimport {\n getSkillsSourceDir,\n getLegacySkillsSourceDir,\n LEGACY_SKILLS_DIR,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\n\n/**\n * Source-mirror skills installer (per ADR 0013).\n *\n * Two-stage flow:\n * 1. **writeSkillSources** — render upstream `<packageRoot>/<skill.source>` and\n * write to `<projectRoot>/.teamix-evo/skills-source/<id>/` (the consumer-side\n * source of truth, regenerable, in git).\n * 2. **syncSkillsToIdes** — pure byte-for-byte copy from source dir to each\n * requested IDE mirror path (`.qoder/skills/<id>/`, `.claude/skills/<id>/`).\n * Mirrors are 100% derived; not subject to managed-region preservation.\n *\n * `installSkills` orchestrates both. `updateSkills` re-renders the source with\n * managed-region preservation against the existing source (NOT the mirrors),\n * then re-syncs.\n */\n\nexport interface SkillInstallOptions {\n /** Project root directory */\n projectRoot: string;\n /** Skills package manifest */\n manifest: SkillsPackageManifest;\n /** Template data */\n data: Record<string, unknown>;\n /** Absolute skills package root */\n packageRoot: string;\n /** IDE kinds to install for (intersection with skill.ides is computed) */\n ides: readonly SkillIde[];\n /** Install scope */\n scope: SkillScope;\n /** Optional: limit to specific skill ids */\n onlyIds?: string[];\n}\n\nexport interface SkillInstallResult {\n resources: InstalledResource[];\n count: number;\n}\n\n/**\n * Install (or reinstall) all skills declared in the manifest using the\n * source-mirror flow. Returns InstalledResource records for both source files\n * and IDE mirror files.\n */\nexport async function installSkills(\n options: SkillInstallOptions,\n): Promise<SkillInstallResult> {\n // One-shot lazy migration: rename legacy `.teamix-evo/skills/` to\n // `.teamix-evo/skills-source/` and rewrite manifest target paths if needed.\n // Runs unconditionally on every install; the function short-circuits when\n // there is nothing to migrate.\n await migrateLegacySkillsSourceDir(options.projectRoot);\n\n const { manifest, ides, scope, onlyIds } = options;\n const installed: InstalledResource[] = [];\n\n const targets = manifest.skills.filter(\n (s) => !onlyIds || onlyIds.includes(s.id),\n );\n\n for (const skill of targets) {\n const skillIdes = skill.ides.filter((i) => ides.includes(i));\n if (skillIdes.length === 0) {\n logger.warn(\n `Skill \"${skill.name}\" supports [${skill.ides.join(\n ',',\n )}], no overlap with [${ides.join(',')}]; skipped.`,\n );\n continue;\n }\n\n const sourceRecords = await writeSkillSource(skill, options);\n installed.push(...sourceRecords);\n\n for (const ide of skillIdes) {\n const mirrorRecords = await mirrorSkillToIde(\n skill,\n ide,\n scope,\n options.projectRoot,\n );\n installed.push(...mirrorRecords);\n }\n }\n\n return { resources: installed, count: installed.length };\n}\n\n/**\n * Render upstream skill source(s) and write to `.teamix-evo/skills/<id>/`.\n * Returns InstalledResource records (one per file) describing the source files.\n */\nasync function writeSkillSource(\n skill: SkillEntry,\n options: SkillInstallOptions,\n): Promise<InstalledResource[]> {\n const { data, packageRoot, projectRoot } = options;\n const sourceAbs = path.resolve(packageRoot, skill.source);\n const targetDir = getSkillsSourceDir(projectRoot, skill.name);\n const stat = await fs.stat(sourceAbs);\n const records: InstalledResource[] = [];\n\n if (stat.isFile()) {\n const targetFile = path.join(targetDir, 'SKILL.md');\n const content = await renderSkillContent(sourceAbs, skill, data);\n await writeFileSafe(targetFile, content);\n records.push(makeSourceRecord(skill, targetFile, content));\n logger.debug(` Wrote source: ${targetFile}`);\n return records;\n }\n\n await ensureDir(targetDir);\n const entries = await walkDir(sourceAbs);\n for (const entry of entries) {\n const rel = path.relative(sourceAbs, entry);\n let targetFile = path.join(targetDir, rel);\n if (skill.template && targetFile.endsWith('.hbs')) {\n targetFile = targetFile.slice(0, -4);\n }\n const content =\n skill.template && entry.endsWith('.hbs')\n ? renderTemplate(await loadTemplateFile(entry), { ...data, skill })\n : await fs.readFile(entry, 'utf-8');\n await writeFileSafe(targetFile, content);\n const relWritten = path.relative(targetDir, targetFile);\n records.push(makeSourceRecord(skill, targetFile, content, relWritten));\n logger.debug(` Wrote source: ${targetFile}`);\n }\n return records;\n}\n\n/**\n * Mirror an installed skill source to a single IDE path.\n *\n * Per ADR 0013, mirrors are normally pure byte-for-byte copies of source.\n * However, when the existing mirror file already contains managed-region\n * markers that match the skill's declared `managedRegions`, the writer falls\n * back to a managed-region replacement (#BUG-101) so user-authored notes\n * outside the markers are preserved across `skills update` / `skills sync`.\n * If markers are absent, the full source content is written (backward-compat).\n */\nasync function mirrorSkillToIde(\n skill: SkillEntry,\n ide: SkillIde,\n scope: SkillScope,\n projectRoot: string,\n): Promise<InstalledResource[]> {\n const sourceDir = getSkillsSourceDir(projectRoot, skill.name);\n const adapter = getAdapter(ide);\n const targetDir = adapter.getSkillTargetDir(skill.name, scope, projectRoot);\n const records: InstalledResource[] = [];\n\n const sourceFiles = await walkDir(sourceDir);\n await ensureDir(targetDir);\n for (const src of sourceFiles) {\n const rel = path.relative(sourceDir, src);\n const targetFile = path.join(targetDir, rel);\n const sourceContent = await fs.readFile(src, 'utf-8');\n\n const writtenContent = await writeMirrorContent(\n targetFile,\n sourceContent,\n skill.managedRegions,\n src,\n );\n records.push(\n makeMirrorRecord(skill, targetFile, writtenContent, ide, scope, rel),\n );\n logger.debug(` Mirrored ${ide}:${scope}: ${targetFile}`);\n }\n return records;\n}\n\n/**\n * Write a mirror file with optional managed-region preservation (#BUG-101).\n *\n * Behavior:\n * - Target absent → full write of source.\n * - `managedRegions` empty/undefined OR existing mirror has no matching\n * markers → full overwrite (with drift warning if content differs).\n * - Otherwise → replace each present managed region's content from the\n * source into the existing mirror, preserving content outside markers.\n *\n * Returns the bytes actually written (used for the InstalledResource hash).\n */\nasync function writeMirrorContent(\n targetFile: string,\n sourceContent: string,\n managedRegions: readonly string[] | undefined,\n sourceFile: string,\n): Promise<string> {\n const existing = await readFileOrNull(targetFile);\n\n if (existing === null) {\n await writeFileSafe(targetFile, sourceContent);\n return sourceContent;\n }\n\n const regions = managedRegions ?? [];\n const matchedRegions = regions.filter((id) => hasManagedRegion(existing, id));\n\n if (matchedRegions.length === 0) {\n if (existing !== sourceContent) {\n logger.warn(\n `Mirror drift detected at ${targetFile} — overwriting from source. ` +\n `Edit ${sourceFile} (not the mirror) and re-run \\`npx teamix-evo@latest skills sync\\`.`,\n );\n await writeFileSafe(targetFile, sourceContent);\n return sourceContent;\n }\n return existing;\n }\n\n let merged = existing;\n // ADR 0015: frontmatter is the IDE-facing protocol — always pull from\n // upstream so trigger/description changes propagate through update + sync\n // without requiring uninstall + reinstall. Body outside managed regions\n // remains user-owned.\n const upstreamFm = extractFrontmatter(sourceContent);\n if (upstreamFm) {\n merged = replaceFrontmatter(merged, upstreamFm);\n }\n for (const id of matchedRegions) {\n const newRegion = extractRegionBody(sourceContent, id);\n if (newRegion === null) continue;\n try {\n merged = replaceManagedRegion(merged, id, newRegion);\n } catch {\n // Region present in existing but pattern failed; skip safely.\n }\n }\n if (merged !== existing) {\n await writeFileSafe(targetFile, merged);\n }\n return merged;\n}\n\nfunction extractRegionBody(content: string, id: string): string | null {\n const re = new RegExp(\n `<!-- teamix-evo:managed:start id=\"${escapeRegExp(\n id,\n )}\" -->([\\\\s\\\\S]*?)<!-- teamix-evo:managed:end id=\"${escapeRegExp(\n id,\n )}\" -->`,\n );\n const m = content.match(re);\n if (!m) return null;\n return m[1]!.replace(/^\\n/, '').replace(/\\n$/, '');\n}\n\nasync function renderSkillContent(\n sourceAbs: string,\n skill: SkillEntry,\n data: Record<string, unknown>,\n): Promise<string> {\n if (skill.template ?? sourceAbs.endsWith('.hbs')) {\n const tpl = await loadTemplateFile(sourceAbs);\n return renderTemplate(tpl, { ...data, skill });\n }\n return fs.readFile(sourceAbs, 'utf-8');\n}\n\nfunction makeSourceRecord(\n skill: SkillEntry,\n targetAbs: string,\n content: string,\n rel?: string,\n): InstalledResource {\n const id = rel ? `${skill.id}:source:${rel}` : `${skill.id}:source`;\n return {\n id,\n target: targetAbs,\n hash: computeHash(content),\n strategy: skill.updateStrategy,\n };\n}\n\nfunction makeMirrorRecord(\n skill: SkillEntry,\n targetAbs: string,\n content: string,\n ide: SkillIde,\n scope: SkillScope,\n rel?: string,\n): InstalledResource {\n const id = rel && rel !== 'SKILL.md' ? `${skill.id}:${rel}` : skill.id;\n return {\n id,\n target: targetAbs,\n hash: computeHash(content),\n strategy: skill.updateStrategy,\n ide,\n scope,\n };\n}\n\nexport interface SkillUpdateOptions extends SkillInstallOptions {\n /**\n * Optional: existing installed records (legacy parameter kept for callers that\n * still pass it). The refactored updater consults the file-system source under\n * `.teamix-evo/skills/<id>/` for managed-region preservation, so this is\n * unused by the new flow. Callers should stop passing it.\n */\n installed?: InstalledResource[];\n /**\n * Optional: limit the update to these skill ids. When provided, skills not\n * in the set are skipped (no source rewrite, no mirror). Per ADR 0035,\n * the high-level `runSkillsUpdate` always passes this with the intersection\n * of `keys(lock.skills)` and the current install scope, ensuring update\n * never accidentally installs new skills or skills from a mismatched scope.\n *\n * Type matches `SkillInstallOptions.onlyIds` (mutable `string[] | undefined`).\n */\n onlyIds?: string[];\n}\n\nexport interface SkillUpdateResult {\n resources: InstalledResource[];\n summary: {\n overwritten: number;\n managed: number;\n skipped: number;\n created: number;\n };\n}\n\n/**\n * Update skills with managed-region preservation applied at the SOURCE layer\n * (not the mirrors). After source is rewritten, mirrors are re-synced cleanly.\n */\nexport async function updateSkills(\n options: SkillUpdateOptions,\n): Promise<SkillUpdateResult> {\n const { manifest, ides, scope, projectRoot } = options;\n const idFilter = options.onlyIds ? new Set(options.onlyIds) : null;\n const summary = { overwritten: 0, managed: 0, skipped: 0, created: 0 };\n const updated: InstalledResource[] = [];\n\n for (const skill of manifest.skills) {\n if (idFilter && !idFilter.has(skill.id)) continue;\n const skillIdes = skill.ides.filter((i) => ides.includes(i));\n if (skillIdes.length === 0) continue;\n\n const sourceRecords = await rewriteSkillSource(skill, options, summary);\n updated.push(...sourceRecords);\n\n // Mirrors are always overwritten cleanly from the (now updated) source.\n for (const ide of skillIdes) {\n const mirrorRecords = await mirrorSkillToIde(\n skill,\n ide,\n scope,\n projectRoot,\n );\n updated.push(...mirrorRecords);\n }\n }\n\n return { resources: updated, summary };\n}\n\nasync function rewriteSkillSource(\n skill: SkillEntry,\n options: SkillUpdateOptions,\n summary: SkillUpdateResult['summary'],\n): Promise<InstalledResource[]> {\n const { data, packageRoot, projectRoot } = options;\n const sourceAbs = path.resolve(packageRoot, skill.source);\n const targetDir = getSkillsSourceDir(projectRoot, skill.name);\n const stat = await fs.stat(sourceAbs);\n\n if (!stat.isFile()) {\n await ensureDir(targetDir);\n const entries = await walkDir(sourceAbs);\n const records: InstalledResource[] = [];\n for (const entry of entries) {\n const rel = path.relative(sourceAbs, entry);\n let targetFile = path.join(targetDir, rel);\n if (skill.template && targetFile.endsWith('.hbs')) {\n targetFile = targetFile.slice(0, -4);\n }\n const newContent =\n skill.template && entry.endsWith('.hbs')\n ? renderTemplate(await loadTemplateFile(entry), { ...data, skill })\n : await fs.readFile(entry, 'utf-8');\n const exists = await fileExists(targetFile);\n\n const written = await rewriteSingleFile({\n targetFile,\n newContent,\n exists,\n updateStrategy: skill.updateStrategy,\n managedRegions: skill.managedRegions,\n projectRoot,\n summary,\n });\n const relWritten = path.relative(targetDir, targetFile);\n records.push(makeSourceRecord(skill, targetFile, written, relWritten));\n }\n return records;\n }\n\n // Single-file skill: target = .teamix-evo/skills/<id>/SKILL.md\n const targetFile = path.join(targetDir, 'SKILL.md');\n const newContent = await renderSkillContent(sourceAbs, skill, data);\n const exists = await fileExists(targetFile);\n\n const written = await rewriteSingleFile({\n targetFile,\n newContent,\n exists,\n updateStrategy: skill.updateStrategy,\n managedRegions: skill.managedRegions,\n projectRoot,\n summary,\n });\n return [makeSourceRecord(skill, targetFile, written)];\n}\n\n/**\n * Apply updateStrategy logic to a single file (used by both single-file and\n * directory skill update paths).\n *\n * Returns the content actually on disk after the operation.\n */\nasync function rewriteSingleFile(args: {\n targetFile: string;\n newContent: string;\n exists: boolean;\n updateStrategy: SkillEntry['updateStrategy'];\n managedRegions: readonly string[] | undefined;\n projectRoot: string;\n summary: SkillUpdateResult['summary'];\n}): Promise<string> {\n const {\n targetFile,\n newContent,\n exists,\n updateStrategy,\n managedRegions,\n projectRoot,\n summary,\n } = args;\n\n if (updateStrategy === 'frozen') {\n if (exists) {\n summary.skipped++;\n return (await readFileOrNull(targetFile)) ?? newContent;\n }\n await writeFileSafe(targetFile, newContent);\n summary.created++;\n return newContent;\n }\n\n if (updateStrategy === 'regenerable' || !exists) {\n if (exists) {\n await backupFile(targetFile, projectRoot);\n summary.overwritten++;\n } else {\n summary.created++;\n }\n await writeFileSafe(targetFile, newContent);\n return newContent;\n }\n\n // managed: preserve outside-region content from the existing SOURCE.\n // Per ADR 0015, the YAML frontmatter is part of the skill's PROTOCOL\n // (name / description / trigger contract) and MUST always follow the\n // upstream package — only the body outside managed regions is treated\n // as user-owned. We therefore overlay the upstream frontmatter first,\n // then apply managed-region replacement on the body.\n const current = await readFileOrNull(targetFile);\n let merged = current ?? newContent;\n const upstreamFm = extractFrontmatter(newContent);\n if (upstreamFm) {\n merged = replaceFrontmatter(merged, upstreamFm);\n }\n for (const regionId of managedRegions ?? []) {\n const re = new RegExp(\n `<!-- teamix-evo:managed:start id=\"${escapeRegExp(\n regionId,\n )}\" -->([\\\\s\\\\S]*?)<!-- teamix-evo:managed:end id=\"${escapeRegExp(\n regionId,\n )}\" -->`,\n );\n const match = newContent.match(re);\n if (match) {\n const region = match[1]!.replace(/^\\n/, '').replace(/\\n$/, '');\n try {\n merged = replaceManagedRegion(merged, regionId, region);\n } catch {\n logger.warn(\n `Managed region \"${regionId}\" not found in ${targetFile}. Skipped.`,\n );\n }\n }\n }\n if (merged !== current) {\n await backupFile(targetFile, projectRoot);\n await writeFileSafe(targetFile, merged);\n }\n summary.managed++;\n return merged;\n}\n\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Sync existing skill sources to the requested IDE mirror paths.\n *\n * Used by:\n * - `skills add` (immediate mirror after source write — handled by installSkills)\n * - `skills sync` (re-mirror after the user adds an IDE or moves machines)\n * - `skills update` (re-mirror after source is rewritten)\n *\n * `onlyIds` lets the caller limit which skills are synced.\n */\nexport interface SkillSyncOptions {\n projectRoot: string;\n /** Skills present in the source dir to mirror (caller derives from lock). */\n skills: ReadonlyArray<{\n id: string;\n name: string;\n updateStrategy: SkillEntry['updateStrategy'];\n /** Managed-region ids for region-aware mirror sync. */\n managedRegions?: readonly string[];\n }>;\n ides: readonly SkillIde[];\n scope: SkillScope;\n onlyIds?: string[];\n}\n\nexport interface SkillSyncResult {\n resources: InstalledResource[];\n count: number;\n}\n\n/**\n * Mirror existing source dirs (`.teamix-evo/skills/<id>/`) to the given IDE\n * paths. Pure byte-for-byte copy — no rendering, no merge.\n */\nexport async function syncSkillsToIdes(\n options: SkillSyncOptions,\n): Promise<SkillSyncResult> {\n // One-shot lazy migration so a stale `.teamix-evo/skills/` from a prior CLI\n // version is moved to the new layout before we walk source dirs.\n await migrateLegacySkillsSourceDir(options.projectRoot);\n\n const { projectRoot, skills, ides, scope, onlyIds } = options;\n const out: InstalledResource[] = [];\n\n const targets = skills.filter((s) => !onlyIds || onlyIds.includes(s.id));\n for (const skill of targets) {\n const sourceDir = getSkillsSourceDir(projectRoot, skill.name);\n if (!(await fileExists(sourceDir))) {\n logger.warn(\n `Skill \"${skill.id}\" has no source at ${sourceDir}; skipped.`,\n );\n continue;\n }\n for (const ide of ides) {\n const adapter = getAdapter(ide);\n const targetDir = adapter.getSkillTargetDir(\n skill.name,\n scope,\n projectRoot,\n );\n await ensureDir(targetDir);\n const sourceFiles = await walkDir(sourceDir);\n for (const src of sourceFiles) {\n const rel = path.relative(sourceDir, src);\n const targetFile = path.join(targetDir, rel);\n const sourceContent = await fs.readFile(src, 'utf-8');\n\n // Region-aware mirror write (#BUG-101): keep user content outside\n // managed markers when the mirror already has them; otherwise full\n // overwrite (with drift warning).\n const writtenContent = await writeMirrorContent(\n targetFile,\n sourceContent,\n skill.managedRegions,\n src,\n );\n out.push({\n id: rel === 'SKILL.md' ? skill.id : `${skill.id}:${rel}`,\n target: targetFile,\n hash: computeHash(writtenContent),\n strategy: skill.updateStrategy,\n ide,\n scope,\n });\n }\n }\n }\n return { resources: out, count: out.length };\n}\n\n/**\n * One-shot migration of the consumer-side skill source directory from the\n * legacy `<projectRoot>/.teamix-evo/skills/` layout to the current\n * `<projectRoot>/.teamix-evo/skills-source/` layout (Init landing plan §A3).\n *\n * Behavior:\n * - When **only** the legacy dir exists → rename it to `skills-source`.\n * - When both exist → keep `skills-source` authoritative; warn that legacy\n * `skills/` is now stale (caller may delete manually).\n * - When neither exists or only `skills-source/` exists → no-op.\n *\n * Side effects:\n * - Updates `InstalledManifest` resources whose `target` still references the\n * legacy `.teamix-evo/skills/` path so subsequent `findInstalledPackage` /\n * uninstall lookups don't dangle.\n *\n * Failures are logged and swallowed: the rest of the install/sync should not\n * be blocked by a best-effort migration step.\n */\nexport async function migrateLegacySkillsSourceDir(\n projectRoot: string,\n): Promise<void> {\n const legacyDir = getLegacySkillsSourceDir(projectRoot);\n const newDir = getSkillsSourceDir(projectRoot);\n\n let legacyExists = false;\n let newExists = false;\n try {\n legacyExists = (await fs.stat(legacyDir)).isDirectory();\n } catch {\n legacyExists = false;\n }\n try {\n newExists = (await fs.stat(newDir)).isDirectory();\n } catch {\n newExists = false;\n }\n\n if (!legacyExists) return;\n if (newExists) {\n logger.warn(\n `Detected stale legacy skills source dir at ${legacyDir} alongside ${newDir}; ` +\n `the new layout takes precedence — you can safely delete the legacy dir.`,\n );\n return;\n }\n\n try {\n await fs.rename(legacyDir, newDir);\n logger.info(\n `Migrated skills source dir: \\`.teamix-evo/${LEGACY_SKILLS_DIR}/\\` → \\`.teamix-evo/skills-source/\\``,\n );\n } catch (err) {\n logger.warn(\n `Failed to rename legacy skills source dir (${getErrorMessage(\n err,\n )}); leaving as-is. New skills will install under the new layout.`,\n );\n return;\n }\n\n // Rewrite manifest targets that still reference the legacy path. We match\n // both POSIX and platform-native separators because Windows installs may\n // have stored back-slashed absolute paths.\n try {\n const manifest = await readInstalledManifest(projectRoot);\n if (!manifest) return;\n const legacyFragmentPosix = `/.teamix-evo/${LEGACY_SKILLS_DIR}/`;\n const newFragmentPosix = `/.teamix-evo/skills-source/`;\n const legacyFragmentNative = `${path.sep}.teamix-evo${path.sep}${LEGACY_SKILLS_DIR}${path.sep}`;\n const newFragmentNative = `${path.sep}.teamix-evo${path.sep}skills-source${path.sep}`;\n let touched = 0;\n for (const pkg of manifest.installed) {\n for (const r of pkg.resources) {\n if (typeof r.target !== 'string') continue;\n const before = r.target;\n let after = before.replace(legacyFragmentPosix, newFragmentPosix);\n after = after.replace(legacyFragmentNative, newFragmentNative);\n if (after !== before) {\n r.target = after;\n touched += 1;\n }\n }\n }\n if (touched > 0) {\n await writeInstalledManifest(projectRoot, manifest);\n logger.debug(\n `Rewrote ${touched} manifest target(s) to the new skills-source path.`,\n );\n }\n } catch (err) {\n logger.warn(\n `Migrated skills source dir but failed to update manifest paths (${getErrorMessage(\n err,\n )}); manifest may still reference legacy paths.`,\n );\n }\n}\n\n/**\n * Prune empty IDE skill directories under each adapter's skill root.\n *\n * Some workflows leave behind empty `<ide-root>/skills/<id>/` shells — e.g.\n * the upstream package dropped a skill, the user toggled it out via\n * `onlyIds`, or a partial mirror failed mid-write and removed the SKILL.md\n * but not the parent dir. Per the Init landing plan §G, every install /\n * sync run sweeps these out so the IDE side stays tidy.\n *\n * Safety:\n * - Only completely empty dirs are removed (no SKILL.md AND no other files).\n * - Non-empty dirs without SKILL.md are LEFT ALONE; deciding whether they\n * are user content vs stale mirror is out of scope for this best-effort\n * pass.\n * - All errors are swallowed; this is decoration, never a hard failure.\n *\n * Returns the list of absolute paths that were removed (for diagnostics).\n */\nexport async function pruneEmptyIdeSkillDirs(args: {\n projectRoot: string;\n ides: readonly SkillIde[];\n scope: SkillScope;\n}): Promise<string[]> {\n const removed: string[] = [];\n for (const ide of args.ides) {\n const adapter = getAdapter(ide);\n // Use a placeholder name to derive the per-IDE skill root, then take\n // dirname — every adapter returns `<root>/<name>/` shape.\n const placeholderDir = adapter.getSkillTargetDir(\n '__placeholder__',\n args.scope,\n args.projectRoot,\n );\n const skillsRoot = path.dirname(placeholderDir);\n let entries: string[];\n try {\n entries = await fs.readdir(skillsRoot);\n } catch {\n continue;\n }\n for (const name of entries) {\n const dir = path.join(skillsRoot, name);\n let stat;\n try {\n stat = await fs.stat(dir);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) continue;\n let children: string[];\n try {\n children = await fs.readdir(dir);\n } catch {\n continue;\n }\n // Skip dirs that still contain a SKILL.md — they're live.\n if (children.some((c) => c === 'SKILL.md')) continue;\n // Only delete completely empty dirs; preserve any user content\n // sitting in a SKILL.md-less directory.\n if (children.length !== 0) continue;\n try {\n await fs.rmdir(dir);\n removed.push(dir);\n logger.debug(`Pruned empty IDE skill dir: ${dir}`);\n } catch {\n // Best-effort; ignore.\n }\n }\n }\n return removed;\n}\n\n/**\n * Remove all installed skill files. Returns the absolute paths removed.\n * After files are unlinked, walks up the directory tree pruning empty dirs\n * until a non-empty ancestor is reached (#33).\n */\nexport async function removeSkillFiles(\n records: InstalledResource[],\n): Promise<string[]> {\n const removed: string[] = [];\n for (const r of records) {\n try {\n await fs.unlink(r.target);\n removed.push(r.target);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n logger.warn(`Failed to remove ${r.target}: ${getErrorMessage(err)}`);\n }\n }\n }\n // Walk-up empty-dir prune. Collect immediate parents, then for each, walk\n // up the tree calling rmdir as long as the dir is empty. Bound the walk\n // to a small depth to prevent runaway in pathological filesystems.\n const startDirs = new Set(records.map((r) => path.dirname(r.target)));\n for (const startDir of startDirs) {\n let dir = startDir;\n for (let depth = 0; depth < 8; depth++) {\n try {\n const entries = await fs.readdir(dir);\n if (entries.length !== 0) break;\n await fs.rmdir(dir);\n } catch {\n break;\n }\n dir = path.dirname(dir);\n }\n }\n return removed;\n}\n","import * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { SkillScope } from '@teamix-evo/registry';\nimport type { IdeAdapter } from './IdeAdapter.js';\n\n/**\n * Qoder IDE adapter.\n * Skill paths:\n * - project: <projectRoot>/.qoder/skills/<name>/\n * - global: ~/.qoder/skills/<name>/\n */\nexport class QoderAdapter implements IdeAdapter {\n readonly kind = 'qoder' as const;\n readonly name = 'qoder';\n\n getProjectRoot(): string {\n return process.cwd();\n }\n\n detectIde(): boolean {\n // MVP: default to true. Future: check environment variables\n return true;\n }\n\n getSkillTargetDir(\n skillName: string,\n scope: SkillScope,\n projectRoot?: string,\n ): string {\n const base =\n scope === 'global'\n ? path.join(os.homedir(), '.qoder')\n : path.join(projectRoot ?? this.getProjectRoot(), '.qoder');\n return path.join(base, 'skills', skillName);\n }\n}\n","import * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { SkillScope } from '@teamix-evo/registry';\nimport type { IdeAdapter } from './IdeAdapter.js';\n\n/**\n * Claude Code IDE adapter.\n * Skill paths:\n * - project: <projectRoot>/.claude/skills/<name>/\n * - global: ~/.claude/skills/<name>/\n */\nexport class ClaudeAdapter implements IdeAdapter {\n readonly kind = 'claude' as const;\n readonly name = 'claude';\n\n getProjectRoot(): string {\n return process.cwd();\n }\n\n detectIde(): boolean {\n // Best-effort: presence of .claude/ in cwd or CLAUDECODE env var.\n return Boolean(process.env.CLAUDECODE);\n }\n\n getSkillTargetDir(\n skillName: string,\n scope: SkillScope,\n projectRoot?: string,\n ): string {\n const base =\n scope === 'global'\n ? path.join(os.homedir(), '.claude')\n : path.join(projectRoot ?? this.getProjectRoot(), '.claude');\n return path.join(base, 'skills', skillName);\n }\n}\n","import type { SkillIde } from '@teamix-evo/registry';\nimport type { IdeAdapter } from './IdeAdapter.js';\nimport { QoderAdapter } from './QoderAdapter.js';\nimport { ClaudeAdapter } from './ClaudeAdapter.js';\n\nexport type { IdeAdapter } from './IdeAdapter.js';\nexport { QoderAdapter } from './QoderAdapter.js';\nexport { ClaudeAdapter } from './ClaudeAdapter.js';\n\n/** All supported IDE kinds (also default selection set for skills) */\nexport const ALL_IDE_KINDS: readonly SkillIde[] = ['qoder', 'claude'] as const;\n\n/**\n * Get the adapter for a specific IDE kind.\n */\nexport function getAdapter(kind: SkillIde): IdeAdapter {\n switch (kind) {\n case 'qoder':\n return new QoderAdapter();\n case 'claude':\n return new ClaudeAdapter();\n default: {\n const _exhaustive: never = kind;\n throw new Error(`Unsupported IDE kind: ${_exhaustive as string}`);\n }\n }\n}\n\n/**\n * Detect the current IDE environment and return the appropriate adapter.\n * MVP: prefers Qoder; falls back to Claude if CLAUDECODE env is set.\n */\nexport function detectIde(): IdeAdapter {\n const claude = new ClaudeAdapter();\n if (claude.detectIde()) return claude;\n return new QoderAdapter();\n}\n","import Handlebars from 'handlebars';\nimport * as fs from 'node:fs/promises';\n\n// Register custom helpers\nHandlebars.registerHelper('lowercase', (str: unknown) => {\n return typeof str === 'string'\n ? str.toLowerCase()\n : String(str ?? '').toLowerCase();\n});\n\n/** LRU-style compilation cache to avoid recompiling the same template */\nconst compiledCache = new Map<string, HandlebarsTemplateDelegate>();\nconst MAX_CACHE_SIZE = 64;\n\nfunction getCompiledTemplate(\n templateContent: string,\n): HandlebarsTemplateDelegate {\n let compiled = compiledCache.get(templateContent);\n if (!compiled) {\n if (compiledCache.size >= MAX_CACHE_SIZE) {\n // Evict oldest entry\n const firstKey = compiledCache.keys().next().value!;\n compiledCache.delete(firstKey);\n }\n compiled = Handlebars.compile(templateContent, { noEscape: true });\n compiledCache.set(templateContent, compiled);\n }\n return compiled;\n}\n\n/**\n * Render a Handlebars template string with the given data.\n */\nexport function renderTemplate(\n templateContent: string,\n data: Record<string, unknown>,\n): string {\n const compiled = getCompiledTemplate(templateContent);\n return compiled(data);\n}\n\n/**\n * Load template file content from disk.\n */\nexport async function loadTemplateFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Resolve a source path — handles _template/ prefix by resolving from packageRoot.\n */\nexport function resolveSourcePath(\n source: string,\n variantDir: string,\n packageRoot: string,\n): string {\n if (source.startsWith('_template/')) {\n return path.join(packageRoot, source);\n }\n return path.join(variantDir, source);\n}\n\n/**\n * Recursively walk a directory and return all file paths.\n */\nexport async function walkDir(dir: string): Promise<string[]> {\n const files: string[] = [];\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n files.push(...(await walkDir(fullPath)));\n } else if (entry.isFile()) {\n files.push(fullPath);\n }\n }\n\n return files;\n}\n\n/**\n * Locate the root directory of an installed npm package by resolving its\n * `package.json`. Used to read token source CSS and variant manifests.\n */\nexport function resolveTokensPackageRoot(packageName: string): string {\n const pkgJson = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJson);\n}\n","import * as path from 'node:path';\nimport { writeFileSafe, fileExists } from './fs.js';\nimport { getErrorMessage } from './error.js';\nimport { logger } from './logger.js';\n\n/**\n * `.mcp.json` content launched by Cursor / Claude Code / Cline.\n *\n * Kept in sync with the scaffold writer in `@teamix-evo/create`. Any change\n * here MUST be mirrored there (see `packages/create/src/orchestrator.ts`).\n */\nconst MCP_JSON_CONTENT = {\n mcpServers: {\n 'teamix-evo': {\n command: 'npx',\n args: ['-y', '@teamix-evo/mcp'],\n },\n },\n} as const;\n\n/**\n * Ensure that `<projectRoot>/.mcp.json` exists.\n *\n * This is called from the incremental entry points (`tokens init`, `skills\n * add`, `ui init`) so projects that adopted teamix-evo without `create` still\n * get the MCP wiring (#BUG-103). Existing files are never overwritten — users\n * may have customised them.\n *\n * Returns `'created'` on first write, `'exists'` if a file is already present,\n * `'failed'` if writing failed (logged as a warning; never throws).\n */\nexport async function ensureMcpJson(\n projectRoot: string,\n): Promise<'created' | 'exists' | 'failed'> {\n const mcpPath = path.join(projectRoot, '.mcp.json');\n if (await fileExists(mcpPath)) return 'exists';\n try {\n await writeFileSafe(\n mcpPath,\n JSON.stringify(MCP_JSON_CONTENT, null, 2) + '\\n',\n );\n logger.debug(`Wrote .mcp.json → ${mcpPath}`);\n return 'created';\n } catch (err) {\n logger.warn(`Failed to write .mcp.json: ${getErrorMessage(err)}`);\n return 'failed';\n }\n}\n","import type {\n ProjectConfig,\n InstalledManifest,\n InstalledResource,\n SkillIde,\n SkillScope,\n SkillsLock,\n SkillsPackageManifest,\n} from '@teamix-evo/registry';\nimport { loadSkillsData } from './skills-client.js';\nimport { installSkills, pruneEmptyIdeSkillDirs } from './skills-installer.js';\nimport {\n ensureTeamixDir,\n readProjectConfig,\n writeProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n readSkillsLock,\n writeSkillsLock,\n readTokensVariant,\n} from './state.js';\nimport { logger } from '../utils/logger.js';\nimport { ensureMcpJson } from '../utils/mcp.js';\n\nconst DEFAULT_SKILLS_PACKAGE = '@teamix-evo/skills';\nconst FLAT_VARIANT = '_flat';\n\n// ─── runSkillsInit ────────────────────────────────────────────────────────────\n// Bulk bootstrap: install every skill in the manifest that matches the current\n// tokens variant + install scope (per ADR 0033). No skill ids accepted —\n// granular adds go through `runSkillsAdd`. Verb split per ADR 0034.\n\nexport interface RunSkillsInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Target IDEs to inject skills into. Required (bulk has no fallback source). */\n ides: readonly SkillIde[];\n /** Install scope. Required (bulk has no fallback source). */\n scope: SkillScope;\n /** IDE identifier written into config.ide when bootstrapping a fresh config (defaults to \"qoder\"). */\n ide?: string;\n /** Override the skills package name (defaults to \"@teamix-evo/skills\"). */\n packageName?: string;\n}\n\nexport type RunSkillsInitResult =\n | {\n status: 'installed';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n skillCount: number;\n fileCount: number;\n resources: InstalledResource[];\n addedSkillIds: string[];\n skippedSkillIds: string[];\n /**\n * Always `[]` for `runSkillsInit` — bulk bootstrap deliberately does not\n * surface upgrade hints (only `runSkillsAdd` does, ADR 0034). Kept on\n * the type so the result shape stays consistent with `RunSkillsAddResult`\n * and `finalizeSkillsInstall`'s return.\n */\n outdatedSkills: OutdatedSkillInfo[];\n }\n | {\n /** Returned when a skills package is already installed and bulk has nothing new to add. */\n status: 'already-initialized';\n };\n\n/**\n * Programmatic equivalent of `teamix-evo skills init`.\n *\n * Installs every manifest skill that matches the current tokens variant +\n * install scope (per ADR 0033 scope filter). Re-running on a project whose\n * `packages.skills` is already configured AND has no missing candidates\n * returns `'already-initialized'`.\n */\nexport async function runSkillsInit(\n options: RunSkillsInitOptions,\n): Promise<RunSkillsInitResult> {\n const { projectRoot } = options;\n const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;\n const ides = [...options.ides] as SkillIde[];\n const scope = options.scope;\n if (ides.length === 0) {\n throw new Error('At least one IDE must be selected.');\n }\n\n await ensureTeamixDir(projectRoot);\n const existingConfig = await readProjectConfig(projectRoot);\n const existingSkillsCfg = existingConfig?.packages?.skills;\n\n const { manifest, data, packageRoot } = await loadSkillsData(packageName);\n const currentTokensVariant = await readTokensVariant(projectRoot);\n\n const existing = await readExistingState(projectRoot, packageName);\n\n // ADR 0033 + tokens variant: filter manifest skills to those eligible for\n // this install scope and current variant.\n const candidateIds = manifest.skills\n .filter((s) => {\n const effectiveScope = s.scope ?? 'project';\n if (effectiveScope !== scope) {\n logger.debug(\n `Skipping skill \"${s.id}\" (scope=${effectiveScope}): current install scope is \"${scope}\". Use \\`skills add ${s.id} --scope ${effectiveScope}\\` to install.`,\n );\n return false;\n }\n if (!s.variant) return true;\n if (!currentTokensVariant) {\n logger.debug(\n `Skipping variant-bound skill \"${s.id}\" (variant=${s.variant}): no tokens variant installed; will be picked up when \"tokens init\" runs.`,\n );\n return false;\n }\n if (s.variant !== currentTokensVariant) {\n logger.debug(\n `Skipping variant-bound skill \"${s.id}\" (variant=${s.variant}): current tokens variant is \"${currentTokensVariant}\".`,\n );\n return false;\n }\n return true;\n })\n .map((s) => s.id);\n\n // Partition candidate skills the same way `runSkillsAdd` does: brand-new go\n // to `onlyIds`; already installed and at-or-above manifest version go to\n // `skippedSkillIds`; already installed but with `lock.version < manifest.version`\n // surface as `outdatedSkills` so callers can suggest `skills update <id>`.\n const { onlyIds, skippedSkillIds, outdatedSkills } = partitionByVersion(\n candidateIds,\n manifest,\n existing,\n );\n\n // Idempotent fast path: nothing new and nothing outdated. Preserve the\n // historical `already-initialized` status only when there's literally\n // nothing for the caller to act on; if any skill is outdated we fall\n // through to the empty-install fast path below so the upgrade hint is\n // surfaced to the CLI layer.\n if (\n existingSkillsCfg &&\n onlyIds.length === 0 &&\n outdatedSkills.length === 0\n ) {\n return { status: 'already-initialized' };\n }\n\n // Empty-install fast path mirrors `runSkillsAdd`: nothing new to install,\n // but at least one outdated skill needs to be reported.\n if (onlyIds.length === 0) {\n return {\n status: 'installed',\n packageName,\n version: existingSkillsCfg?.version ?? manifest.version,\n ides,\n scope,\n skillCount: 0,\n fileCount: 0,\n resources: [],\n addedSkillIds: [],\n skippedSkillIds,\n outdatedSkills,\n };\n }\n\n return finalizeSkillsInstall({\n projectRoot,\n packageName,\n ideIdent: options.ide ?? 'qoder',\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n skippedSkillIds,\n outdatedSkills,\n existing,\n existingConfig,\n });\n}\n\n// ─── runSkillsAdd ─────────────────────────────────────────────────────────────\n// Incremental: install named skill ids. `names` is required (≥ 1).\n// Skills already present are skipped. ADR 0034.\n\nexport interface RunSkillsAddOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /**\n * Skill ids to add. **Required, must contain at least one id.** Use\n * {@link runSkillsInit} for bulk bootstrap (no ids).\n */\n names: readonly string[];\n /** Target IDEs. Optional — falls back to the previously installed config. */\n ides?: readonly SkillIde[];\n /** Install scope. Optional — falls back to existing config. */\n scope?: SkillScope;\n /** IDE identifier written into config.ide when bootstrapping a fresh config (defaults to \"qoder\"). */\n ide?: string;\n /** Override the skills package name (defaults to \"@teamix-evo/skills\"). */\n packageName?: string;\n}\n\n/**\n * Detail for an already-installed skill whose locked version is older than\n * the manifest's latest version. Use `skills update <id>` to upgrade.\n */\nexport interface OutdatedSkillInfo {\n /** Skill id */\n id: string;\n /** Version recorded in `.teamix-evo/skills.lock.json` */\n installed: string;\n /** Version available in the upstream manifest (i.e. `npx` resolved `@latest`) */\n latest: string;\n}\n\nexport type RunSkillsAddResult = {\n status: 'installed';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n /** Number of skills that were freshly added in this call. */\n skillCount: number;\n /** Number of files written by `installSkills` for the freshly added skills. */\n fileCount: number;\n /** InstalledResource records for the freshly added skills only. */\n resources: InstalledResource[];\n /** Skill ids that were freshly added in this call. */\n addedSkillIds: string[];\n /**\n * Skill ids that were requested but already installed at the latest version;\n * nothing to do. Outdated installs are reported separately via\n * {@link outdatedSkills}.\n */\n skippedSkillIds: string[];\n /**\n * Skill ids that were requested, are already installed, but whose locked\n * version is older than the manifest version. Caller should surface a hint\n * recommending `skills update <id>`.\n */\n outdatedSkills: OutdatedSkillInfo[];\n};\n\n/**\n * Programmatic equivalent of `teamix-evo skills add <names...>` (ADR 0034).\n *\n * Installs only the listed skills. Skills already present are skipped (use\n * `skills update` to refresh). `ides` / `scope` may be omitted — they fall\n * back to the previously installed config.\n *\n * Throws if `names` is empty — bulk bootstrap belongs to {@link runSkillsInit}.\n */\nexport async function runSkillsAdd(\n options: RunSkillsAddOptions,\n): Promise<RunSkillsAddResult> {\n if (!options.names || options.names.length === 0) {\n throw new Error(\n 'runSkillsAdd requires at least one skill id. Use runSkillsInit() for bulk install.',\n );\n }\n\n const { projectRoot, names: requestedNames } = options;\n const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;\n\n await ensureTeamixDir(projectRoot);\n\n const existingConfig = await readProjectConfig(projectRoot);\n const existingSkillsCfg = existingConfig?.packages?.skills;\n\n // Resolve ides/scope: explicit option wins, else fall back to existing config.\n const ides = (\n options.ides && options.ides.length > 0\n ? [...options.ides]\n : existingSkillsCfg?.ides\n ? [...existingSkillsCfg.ides]\n : []\n ) as SkillIde[];\n const scope = (options.scope ?? existingSkillsCfg?.scope) as\n | SkillScope\n | undefined;\n if (ides.length === 0) {\n throw new Error('At least one IDE must be selected.');\n }\n if (!scope) {\n throw new Error('Scope must be specified (project | global).');\n }\n\n const { manifest, data, packageRoot } = await loadSkillsData(packageName);\n\n // Validate requested names against manifest.\n const known = new Set(manifest.skills.map((s) => s.id));\n const unknown = requestedNames.filter((n) => !known.has(n));\n if (unknown.length > 0) {\n const available = [...known].join(', ');\n throw new Error(\n `Unknown skill id(s): ${unknown.join(', ')}. Available: ${\n available || '(none)'\n }.`,\n );\n }\n\n // ADR 0033: warn when explicitly naming a skill whose declared scope\n // doesn't match the current install scope. Don't block — explicit\n // naming overrides the default; user takes responsibility.\n for (const s of manifest.skills) {\n if (requestedNames.includes(s.id) && s.scope && s.scope !== scope) {\n logger.warn(\n `\"${s.id}\" 推荐 ${s.scope} scope 安装。当前以 ${scope} scope 强制安装,可能与另一 scope 的副本冲突。建议改用 \\`skills add ${s.id} --scope ${s.scope}\\`。`,\n );\n }\n }\n\n const existing = await readExistingState(projectRoot, packageName);\n\n // Partition requested names: already-installed-and-up-to-date go to\n // `skippedSkillIds`; already-installed-but-older go to `outdatedSkills`\n // (caller surfaces an upgrade hint); brand-new go to `onlyIds`.\n const { onlyIds, skippedSkillIds, outdatedSkills } = partitionByVersion(\n requestedNames,\n manifest,\n existing,\n );\n\n // Incremental fast path: nothing new to install.\n if (onlyIds.length === 0) {\n return {\n status: 'installed',\n packageName,\n version: existingSkillsCfg?.version ?? manifest.version,\n ides,\n scope,\n skillCount: 0,\n fileCount: 0,\n resources: [],\n addedSkillIds: [],\n skippedSkillIds,\n outdatedSkills,\n };\n }\n\n return finalizeSkillsInstall({\n projectRoot,\n packageName,\n ideIdent: options.ide ?? 'qoder',\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n skippedSkillIds,\n outdatedSkills,\n existing,\n existingConfig,\n });\n}\n\n// ─── partition helper (shared by init + add) ────────────────────────────────\n// Split a list of skill ids into three buckets based on `existing` lock state\n// vs `manifest` version. `onlyIds` (new) → drives `installSkills`;\n// `skippedSkillIds` (already at latest) and `outdatedSkills` (lock < manifest)\n// are surfaced to the CLI for messaging. Pre-ADR-0013 legacy installs whose\n// lock is missing fall through to `skippedSkillIds` (conservative — don't\n// nag a user we can't reliably version-check).\nfunction partitionByVersion(\n ids: readonly string[],\n manifest: SkillsPackageManifest,\n existing: ExistingState,\n): {\n onlyIds: string[];\n skippedSkillIds: string[];\n outdatedSkills: OutdatedSkillInfo[];\n} {\n const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));\n const onlyIds: string[] = [];\n const skippedSkillIds: string[] = [];\n const outdatedSkills: OutdatedSkillInfo[] = [];\n for (const name of ids) {\n if (!existing.skillIds.has(name)) {\n onlyIds.push(name);\n continue;\n }\n const installedVer = existing.lock?.skills?.[name]?.version;\n const latestVer = manifestById.get(name)?.version;\n if (\n installedVer &&\n latestVer &&\n compareSemver(installedVer, latestVer) < 0\n ) {\n outdatedSkills.push({\n id: name,\n installed: installedVer,\n latest: latestVer,\n });\n } else {\n skippedSkillIds.push(name);\n }\n }\n return { onlyIds, skippedSkillIds, outdatedSkills };\n}\n\n// ─── semver helpers (light, no dep) ───────────────────────────────────────────\n// Only needed by `runSkillsAdd` to decide whether an already-installed skill is\n// truly outdated (installed < manifest). We deliberately avoid pulling in a\n// `semver` runtime dep; manifest versions are validated against\n// `^\\d+\\.\\d+\\.\\d+/` by the registry schema, so a numeric major.minor.patch\n// triple is sufficient. Pre-release / build metadata is ignored — if two\n// versions share the same triple they're considered equal here.\nfunction parseSemverTriple(v: string): [number, number, number] | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(v);\n if (!m) return null;\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\n/** -1 if a < b, 0 if equal (or unparseable + identical strings), 1 if a > b. */\nfunction compareSemver(a: string, b: string): number {\n const pa = parseSemverTriple(a);\n const pb = parseSemverTriple(b);\n if (!pa || !pb) {\n if (a === b) return 0;\n return a < b ? -1 : 1;\n }\n for (let i = 0; i < 3; i++) {\n if (pa[i]! !== pb[i]!) return pa[i]! < pb[i]! ? -1 : 1;\n }\n return 0;\n}\n\n// ─── shared internals ─────────────────────────────────────────────────────────\n\ninterface ExistingState {\n installed: InstalledManifest | null;\n pkg:\n | {\n package: string;\n resources: InstalledResource[];\n }\n | undefined;\n lock: SkillsLock | null;\n skillIds: Set<string>;\n}\n\nasync function readExistingState(\n projectRoot: string,\n packageName: string,\n): Promise<ExistingState> {\n const installed = await readInstalledManifest(projectRoot);\n const pkg = installed?.installed.find((p) => p.package === packageName);\n const lock = await readSkillsLock(projectRoot);\n const skillIds = new Set<string>([\n ...Object.keys(lock?.skills ?? {}),\n // Legacy fallback: pre-ADR-0013 installs only had manifest.json. Derive\n // skill ids by stripping the trailing :source / :sub-file suffix.\n ...(pkg?.resources ?? []).map((r) => r.id.split(':')[0] ?? r.id),\n ]);\n return { installed, pkg, lock, skillIds };\n}\n\ninterface FinalizeArgs {\n projectRoot: string;\n packageName: string;\n ideIdent: string;\n manifest: SkillsPackageManifest;\n data: Parameters<typeof installSkills>[0]['data'];\n packageRoot: string;\n ides: SkillIde[];\n scope: SkillScope;\n onlyIds: string[];\n skippedSkillIds: string[];\n /** Optional — only populated by `runSkillsAdd`. `runSkillsInit` leaves empty. */\n outdatedSkills?: OutdatedSkillInfo[];\n existing: ExistingState;\n existingConfig: ProjectConfig | null;\n}\n\nasync function finalizeSkillsInstall(args: FinalizeArgs): Promise<{\n status: 'installed';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n skillCount: number;\n fileCount: number;\n resources: InstalledResource[];\n addedSkillIds: string[];\n skippedSkillIds: string[];\n outdatedSkills: OutdatedSkillInfo[];\n}> {\n const {\n projectRoot,\n packageName,\n ideIdent,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n skippedSkillIds,\n outdatedSkills,\n existing,\n existingConfig,\n } = args;\n\n const result = await installSkills({\n projectRoot,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n });\n\n const config: ProjectConfig = existingConfig ?? {\n $schema: 'https://teamix-evo.dev/schema/config/v2.json',\n schemaVersion: 2,\n ide: ideIdent,\n packages: {},\n };\n config.packages.skills = {\n variant: FLAT_VARIANT,\n version: manifest.version,\n ides,\n scope,\n };\n await writeProjectConfig(projectRoot, config);\n\n const installedAt = new Date().toISOString();\n const installedManifest: InstalledManifest = existing.installed ?? {\n schemaVersion: 1,\n installed: [],\n };\n const idx = installedManifest.installed.findIndex(\n (p) => p.package === packageName,\n );\n const mergedResources = mergeInstalledResources(\n existing.pkg?.resources ?? [],\n result.resources,\n );\n const entry = {\n package: packageName,\n variant: FLAT_VARIANT,\n version: manifest.version,\n installedAt,\n resources: mergedResources,\n };\n if (idx >= 0) installedManifest.installed[idx] = entry;\n else installedManifest.installed.push(entry);\n await writeInstalledManifest(projectRoot, installedManifest);\n\n // Update skills source-mirror lock (per ADR 0013).\n const lock: SkillsLock = existing.lock ?? {\n schemaVersion: 1,\n skills: {},\n };\n for (const skillId of onlyIds) {\n const skillDef = manifest.skills.find((s) => s.id === skillId);\n if (!skillDef) continue;\n const mirroredTo = skillDef.ides.filter((i) => ides.includes(i));\n lock.skills[skillId] = {\n version: skillDef.version,\n from: packageName,\n installedAt,\n scope,\n mirroredTo,\n };\n }\n await writeSkillsLock(projectRoot, lock);\n\n // After the install completes, ensure the MCP launcher config exists so\n // Cursor / Claude Code / Cline pick up `@teamix-evo/mcp` automatically\n // (#BUG-103). Existing `.mcp.json` files are preserved.\n await ensureMcpJson(projectRoot);\n\n // Phase 5.G: sweep empty IDE skill dirs left over from prior installs\n // (e.g. a removed upstream skill). Best-effort — swallows errors.\n try {\n await pruneEmptyIdeSkillDirs({ projectRoot, ides, scope });\n } catch {\n // Cleanup is decoration; never a hard failure.\n }\n\n return {\n status: 'installed',\n packageName,\n version: manifest.version,\n ides,\n scope,\n skillCount: onlyIds.length,\n fileCount: result.count,\n resources: result.resources,\n addedSkillIds: onlyIds,\n skippedSkillIds,\n outdatedSkills: outdatedSkills ?? [],\n };\n}\n\nfunction mergeInstalledResources(\n existing: InstalledResource[],\n next: InstalledResource[],\n): InstalledResource[] {\n const map = new Map<string, InstalledResource>();\n const key = (r: InstalledResource): string =>\n `${r.id}|${r.ide ?? ''}|${r.scope ?? ''}`;\n for (const r of existing) map.set(key(r), r);\n for (const r of next) map.set(key(r), r);\n return [...map.values()];\n}\n","import type {\n InstalledResource,\n SkillIde,\n SkillScope,\n SkillsLock,\n} from '@teamix-evo/registry';\nimport { loadSkillsData } from './skills-client.js';\nimport { updateSkills } from './skills-installer.js';\nimport {\n readProjectConfig,\n readInstalledManifest,\n writeProjectConfig,\n writeInstalledManifest,\n readSkillsLock,\n writeSkillsLock,\n} from './state.js';\nimport { logger } from '../utils/logger.js';\n\nconst DEFAULT_SKILLS_PACKAGE = '@teamix-evo/skills';\nconst FLAT_VARIANT = '_flat';\n\n// ─── runSkillsUpdate ──────────────────────────────────────────────────────────\n// ADR 0035: update only refreshes skills that are (a) recorded in the lock and\n// (b) match the current install scope. New skills added to the manifest are NOT\n// auto-installed by update — use `skills add <id>` for that. version-diff\n// short-circuits when nothing has actually changed.\n\nexport interface RunSkillsUpdateOptions {\n /** Absolute project (or global meta) root. */\n projectRoot: string;\n /**\n * Optional: limit the update to these skill ids. Falls back to \"every\n * skill in lock that matches the current install scope\".\n */\n names?: readonly string[];\n /** When true, plan only — no source rewrite, no mirror, no lock write. */\n dryRun?: boolean;\n /** Override the skills package name (defaults to `@teamix-evo/skills`). */\n packageName?: string;\n}\n\nexport interface UpdatePlanItem {\n id: string;\n current: string;\n next: string;\n /** Same as updateStrategy semantics, computed from the manifest. */\n strategy: 'frozen' | 'regenerable' | 'managed';\n /**\n * Predicted action for this skill source file in non-dryRun mode.\n * - `up-to-date` — version unchanged; safe to skip\n * - `version-bump` — version changed; will overwrite/merge per strategy\n */\n action: 'up-to-date' | 'version-bump';\n}\n\nexport type RunSkillsUpdateResult =\n | { status: 'no-skills' }\n | {\n status: 'no-changes';\n packageName: string;\n version: string;\n checkedSkillIds: string[];\n }\n | {\n status: 'dry-run';\n packageName: string;\n currentVersion: string;\n availableVersion: string;\n plan: UpdatePlanItem[];\n }\n | {\n status: 'updated';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n updatedSkillIds: string[];\n skippedSkillIds: string[];\n summary: { overwritten: number; managed: number; skipped: number; created: number };\n resources: InstalledResource[];\n };\n\n/**\n * Programmatic equivalent of `teamix-evo skills update [names...] [--dry-run]`.\n *\n * Per ADR 0035:\n * 1. Range = `keys(lock.skills) ∩ scope-match ∩ (names if given)`\n * 2. version-diff short-circuit when every target id has the same lock\n * version as the manifest\n * 3. New skills (not in lock) are NEVER auto-installed by update\n * 4. lock writeback only touches `targetIds` — existing entries are preserved\n */\nexport async function runSkillsUpdate(\n options: RunSkillsUpdateOptions,\n): Promise<RunSkillsUpdateResult> {\n const { projectRoot, names: requestedNames, dryRun } = options;\n const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;\n\n const config = await readProjectConfig(projectRoot);\n const skillsCfg = config?.packages?.skills;\n if (!skillsCfg) {\n return { status: 'no-skills' };\n }\n\n const ides = (skillsCfg.ides ?? ['qoder', 'claude']) as SkillIde[];\n const scope = (skillsCfg.scope ?? 'project') as SkillScope;\n\n const existingLock = await readSkillsLock(projectRoot);\n if (!existingLock || Object.keys(existingLock.skills).length === 0) {\n return { status: 'no-skills' };\n }\n\n const { manifest, data, packageRoot } = await loadSkillsData(packageName);\n const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));\n\n // Three-gate intersection: lock ∩ scope ∩ names.\n const lockIds = Object.keys(existingLock.skills);\n const requestedSet = requestedNames ? new Set(requestedNames) : null;\n if (requestedSet) {\n const unknown = requestedNames!.filter(\n (n) => !lockIds.includes(n) && !manifestById.has(n),\n );\n if (unknown.length > 0) {\n throw new Error(\n `Unknown skill id(s): ${unknown.join(\n ', ',\n )}. Available (installed): ${lockIds.join(', ') || '(none)'}.`,\n );\n }\n }\n\n const targetIds: string[] = [];\n const skippedSkillIds: string[] = [];\n for (const id of lockIds) {\n if (requestedSet && !requestedSet.has(id)) continue;\n const entry = manifestById.get(id);\n if (!entry) {\n // Lock has it, manifest no longer does (skill removed upstream).\n // Skip without error — uninstall is the user's call.\n logger.debug(\n `Skipping \"${id}\": no longer in upstream manifest. Use \\`skills uninstall ${id}\\` to remove.`,\n );\n skippedSkillIds.push(id);\n continue;\n }\n const effectiveScope = entry.scope ?? 'project';\n if (effectiveScope !== scope) {\n logger.debug(\n `Skipping \"${id}\" (scope=${effectiveScope}): current install scope is \"${scope}\".`,\n );\n skippedSkillIds.push(id);\n continue;\n }\n targetIds.push(id);\n }\n\n // version-diff short-circuit\n const allSame = targetIds.every((id) => {\n const lockVer = existingLock.skills[id]!.version;\n const manVer = manifestById.get(id)!.version;\n return lockVer === manVer;\n });\n if (targetIds.length > 0 && allSame && !dryRun) {\n return {\n status: 'no-changes',\n packageName,\n version: manifest.version,\n checkedSkillIds: targetIds,\n };\n }\n\n if (dryRun) {\n const plan: UpdatePlanItem[] = targetIds.map((id) => {\n const lockVer = existingLock.skills[id]!.version;\n const entry = manifestById.get(id)!;\n const sameVersion = lockVer === entry.version;\n return {\n id,\n current: lockVer,\n next: entry.version,\n strategy: entry.updateStrategy ?? 'managed',\n action: sameVersion ? 'up-to-date' : 'version-bump',\n };\n });\n return {\n status: 'dry-run',\n packageName,\n currentVersion: skillsCfg.version,\n availableVersion: manifest.version,\n plan,\n };\n }\n\n if (targetIds.length === 0) {\n return {\n status: 'updated',\n packageName,\n version: manifest.version,\n ides,\n scope,\n updatedSkillIds: [],\n skippedSkillIds,\n summary: { overwritten: 0, managed: 0, skipped: 0, created: 0 },\n resources: [],\n };\n }\n\n const result = await updateSkills({\n projectRoot,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds: targetIds,\n });\n\n // Update config.version (track the package-level version we last consumed).\n config!.packages.skills = {\n ...skillsCfg,\n version: manifest.version,\n };\n await writeProjectConfig(projectRoot, config!);\n\n // Update installed manifest (replace the package-level entry's resources).\n const installedManifest = (await readInstalledManifest(projectRoot)) ?? {\n schemaVersion: 1 as const,\n installed: [],\n };\n const idx = installedManifest.installed.findIndex(\n (p) => p.package === packageName,\n );\n const installedAt = new Date().toISOString();\n // Merge: keep resources from skills NOT in targetIds (preserve existing\n // entries for skills we didn't touch this round).\n const prior = idx >= 0 ? installedManifest.installed[idx]!.resources : [];\n const targetSet = new Set(targetIds);\n const preserved = prior.filter((r) => {\n const skillId = r.id.split(':')[0];\n return skillId ? !targetSet.has(skillId) : true;\n });\n const entry = {\n package: packageName,\n variant: FLAT_VARIANT,\n version: manifest.version,\n installedAt,\n resources: [...preserved, ...result.resources],\n };\n if (idx >= 0) installedManifest.installed[idx] = entry;\n else installedManifest.installed.push(entry);\n await writeInstalledManifest(projectRoot, installedManifest);\n\n // Update lock — only for targetIds, preserving other entries.\n const lock: SkillsLock = {\n schemaVersion: 1,\n skills: { ...existingLock.skills },\n };\n for (const id of targetIds) {\n const skillDef = manifestById.get(id);\n if (!skillDef) continue;\n const mirroredTo = skillDef.ides.filter((i) => ides.includes(i));\n lock.skills[id] = {\n version: skillDef.version,\n from: packageName,\n installedAt,\n scope,\n mirroredTo,\n };\n }\n await writeSkillsLock(projectRoot, lock);\n\n return {\n status: 'updated',\n packageName,\n version: manifest.version,\n ides,\n scope,\n updatedSkillIds: targetIds,\n skippedSkillIds,\n summary: result.summary,\n resources: result.resources,\n };\n}\n","import type { ProjectConfig, UiAliases } from '@teamix-evo/registry';\nimport { ensureMcpJson } from '../utils/mcp.js';\nimport {\n ensureTeamixDir,\n readProjectConfig,\n writeProjectConfig,\n} from './state.js';\n\nexport const DEFAULT_UI_ALIASES: UiAliases = {\n components: 'src/components/ui',\n hooks: 'src/hooks',\n utils: 'src/lib/utils',\n lib: 'src/lib',\n business: 'src/components/business',\n templates: 'src/templates',\n};\n\nexport const DEFAULT_UI_ICON_LIBRARY = 'lucide';\n\nexport interface RunUiInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Component aliases. Falls back to {@link DEFAULT_UI_ALIASES}. */\n aliases?: Partial<UiAliases>;\n /** Declared icon library (does not trigger code rewrite). Defaults to \"lucide\". */\n iconLibrary?: string;\n /** Whether the project uses TSX (true) or JSX (false). Defaults to true. */\n tsx?: boolean;\n /** Whether the project emits React Server Components markers. Defaults to false. */\n rsc?: boolean;\n /** IDE identifier written into config.ide when bootstrapping a fresh config (defaults to \"qoder\"). */\n ide?: string;\n}\n\nexport type RunUiInitResult =\n | {\n status: 'installed';\n aliases: UiAliases;\n iconLibrary: string;\n tsx: boolean;\n rsc: boolean;\n }\n | {\n status: 'already-initialized';\n };\n\n/**\n * Programmatic equivalent of `teamix-evo ui init`.\n *\n * Writes `packages.ui` into `.teamix-evo/config.json` only — no resource files\n * are touched. Use {@link runUiAdd} afterwards to install component sources.\n */\nexport async function runUiInit(\n options: RunUiInitOptions,\n): Promise<RunUiInitResult> {\n const { projectRoot } = options;\n const ideIdent = options.ide ?? 'qoder';\n\n await ensureTeamixDir(projectRoot);\n\n const existingConfig = await readProjectConfig(projectRoot);\n if (existingConfig?.packages?.ui) {\n return { status: 'already-initialized' };\n }\n\n const aliases: UiAliases = {\n components: options.aliases?.components ?? DEFAULT_UI_ALIASES.components,\n hooks: options.aliases?.hooks ?? DEFAULT_UI_ALIASES.hooks,\n utils: options.aliases?.utils ?? DEFAULT_UI_ALIASES.utils,\n lib: options.aliases?.lib ?? DEFAULT_UI_ALIASES.lib,\n business: options.aliases?.business ?? DEFAULT_UI_ALIASES.business,\n templates: options.aliases?.templates ?? DEFAULT_UI_ALIASES.templates,\n };\n const iconLibrary = options.iconLibrary ?? DEFAULT_UI_ICON_LIBRARY;\n const tsx = options.tsx ?? true;\n const rsc = options.rsc ?? false;\n\n const config: ProjectConfig = existingConfig ?? {\n $schema: 'https://teamix-evo.dev/schema/config/v2.json',\n schemaVersion: 2,\n ide: ideIdent,\n packages: {},\n };\n config.packages.ui = {\n variant: '_flat',\n version: '0.0.0',\n aliases,\n iconLibrary,\n tsx,\n rsc,\n };\n await writeProjectConfig(projectRoot, config);\n\n // Ensure `.mcp.json` exists so editors auto-launch the MCP server even\n // when the user adopted teamix-evo without the create scaffold (#BUG-103).\n await ensureMcpJson(projectRoot);\n\n return {\n status: 'installed',\n aliases,\n iconLibrary,\n tsx,\n rsc,\n };\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport type { UiPackageManifest } from '@teamix-evo/registry';\nimport { loadUiPackageManifest } from '@teamix-evo/registry';\nimport { logger } from '../utils/logger.js';\n\nconst require = createRequire(import.meta.url);\n\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\n/**\n * Load the ui package manifest and optional shared `_data.json`.\n *\n * @param packageName - e.g. \"@teamix-evo/ui\"\n */\nexport async function loadUiData(packageName: string): Promise<{\n manifest: UiPackageManifest;\n data: Record<string, unknown>;\n packageRoot: string;\n}> {\n const packageRoot = resolvePackageRoot(packageName);\n\n logger.debug(`Resolved ui package root: ${packageRoot}`);\n\n const manifest = await loadUiPackageManifest(packageRoot);\n\n let data: Record<string, unknown> = {};\n const dataPath = path.join(packageRoot, '_data.json');\n try {\n const raw = await fs.readFile(dataPath, 'utf-8');\n data = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err;\n }\n logger.debug(`No _data.json found at ${dataPath}, using empty data`);\n }\n\n return { manifest, data, packageRoot };\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport type {\n UiEntry,\n UiPackageManifest,\n UiAliases,\n InstalledResource,\n} from '@teamix-evo/registry';\nimport { resolveUiEntryOrder } from '@teamix-evo/registry';\nimport { backupFile, writeFileSafe, fileExists } from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport { rewriteImports } from '../utils/transform-imports.js';\nimport { logger } from '../utils/logger.js';\nimport { getErrorMessage } from '../utils/error.js';\n\nexport interface UiInstallOptions {\n /** Project root directory */\n projectRoot: string;\n /** UI package manifest */\n manifest: UiPackageManifest;\n /** Absolute ui package root (used to resolve entry source paths) */\n packageRoot: string;\n /**\n * Optional per-entry package root override. When set, entries in the map\n * resolve their `file.source` against the mapped root instead of `packageRoot`.\n * Used by variant-aware packages (biz-ui / templates) that pull in\n * @teamix-evo/ui transitive deps — each entry resolves from its source package.\n */\n entryPackageRoot?: Map<string, string>;\n /** Aliases configured in `packages.ui.aliases` */\n aliases: UiAliases;\n /** Entry ids the user explicitly requested to add */\n requested: string[];\n /** When true, skip writing entries whose target file already exists (frozen-on-add). */\n skipExisting?: boolean;\n}\n\nexport interface UiInstallResult {\n /** Ordered list of entry ids that were processed (deps + requested) */\n orderedIds: string[];\n /** Per-file install records (for InstalledManifest) */\n resources: InstalledResource[];\n /** Aggregate npm dependencies across the installed entries */\n npmDependencies: Record<string, string>;\n /** Number of files written */\n written: number;\n /** Number of files skipped because they already exist (frozen) */\n skipped: number;\n}\n\n/**\n * Install the requested ui entries (transitively resolving registryDependencies).\n * For frozen entries that already exist on disk, the write is skipped — shadcn-style.\n */\nexport async function installUiEntries(\n options: UiInstallOptions,\n): Promise<UiInstallResult> {\n const {\n projectRoot,\n manifest,\n packageRoot,\n entryPackageRoot,\n aliases,\n requested,\n skipExisting = true,\n } = options;\n\n const orderedIds = resolveUiEntryOrder(manifest.entries, requested);\n const idToEntry = new Map(manifest.entries.map((e) => [e.id, e]));\n\n const resources: InstalledResource[] = [];\n const npmDeps: Record<string, string> = {};\n let written = 0;\n let skipped = 0;\n\n for (const id of orderedIds) {\n const entry = idToEntry.get(id);\n if (!entry) continue;\n\n // Aggregate npm deps regardless of whether files were written — the user\n // may have manually deleted node_modules; we want to surface the full set.\n if (entry.dependencies) {\n for (const [name, range] of Object.entries(entry.dependencies)) {\n npmDeps[name] = range;\n }\n }\n\n for (const file of entry.files) {\n const targetAbs = resolveTargetPath(projectRoot, aliases, entry, file);\n const exists = await fileExists(targetAbs);\n\n if (\n exists &&\n skipExisting &&\n (entry.updateStrategy ?? 'frozen') === 'frozen'\n ) {\n logger.info(` skip (frozen, exists): ${rel(projectRoot, targetAbs)}`);\n skipped++;\n continue;\n }\n\n const rootForEntry = entryPackageRoot?.get(entry.id) ?? packageRoot;\n const sourceAbs = path.resolve(rootForEntry, file.source);\n const raw = await fs.readFile(sourceAbs, 'utf-8');\n const transformed = rewriteImports(raw, aliases);\n // Phase 1.A2: any existing user file we are about to overwrite must be\n // backed up under .teamix-evo/.backups/. This applies to:\n // - regenerable entries on re-install,\n // - frozen entries when caller passes overwrite=true (init conflict\n // decision \"shadcn-source: overwrite\").\n if (exists) {\n await backupFile(targetAbs, projectRoot);\n }\n await writeFileSafe(targetAbs, transformed);\n written++;\n logger.info(` write: ${rel(projectRoot, targetAbs)}`);\n\n resources.push({\n id: `${entry.id}:${file.targetName}`,\n target: targetAbs,\n hash: computeHash(transformed),\n strategy: entry.updateStrategy ?? 'frozen',\n });\n }\n }\n\n return {\n orderedIds,\n resources,\n npmDependencies: npmDeps,\n written,\n skipped,\n };\n}\n\nfunction resolveTargetPath(\n projectRoot: string,\n aliases: UiAliases,\n entry: UiEntry,\n file: { targetAlias: string; targetName: string },\n): string {\n const aliasDir = aliases[file.targetAlias as keyof UiAliases];\n if (!aliasDir) {\n throw new Error(\n `Entry \"${entry.id}\" requires alias \"${file.targetAlias}\" but it is not configured.`,\n );\n }\n return path.join(projectRoot, aliasDir, file.targetName);\n}\n\nfunction rel(projectRoot: string, abs: string): string {\n return path.relative(projectRoot, abs);\n}\n\n/**\n * Remove all installed ui resource files and prune empty parent directories.\n */\nexport async function removeUiFiles(\n records: InstalledResource[],\n): Promise<string[]> {\n const removed: string[] = [];\n for (const r of records) {\n try {\n await fs.unlink(r.target);\n removed.push(r.target);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n logger.warn(`Failed to remove ${r.target}: ${getErrorMessage(err)}`);\n }\n }\n }\n const parents = new Set(records.map((r) => path.dirname(r.target)));\n for (const dir of parents) {\n try {\n const entries = await fs.readdir(dir);\n if (entries.length === 0) await fs.rmdir(dir);\n } catch {\n /* ignore */\n }\n }\n return removed;\n}\n","import type { UiAliases } from '@teamix-evo/registry';\n\n/**\n * Map between the ui package's \"developer-time\" import roots and the user's\n * configured aliases. The keys are the source roots used inside ui source\n * files (e.g. `@/utils/cn` references `src/utils/`).\n */\nconst SOURCE_ROOT_TO_ALIAS_KEY: Record<string, keyof UiAliases> = {\n components: 'components',\n hooks: 'hooks',\n utils: 'utils',\n lib: 'lib',\n};\n\n/**\n * Rewrite import specifiers in a UI source file so that the developer-time\n * placeholders (e.g. `@/utils/cn`) resolve to the user's configured aliases\n * (e.g. `@/lib/utils/cn` when `aliases.utils === \"src/lib/utils\"`).\n *\n * Matches both static imports and dynamic imports of the form `@/<root>/<rest>`.\n * Bare `@/` (no segment) and unknown segments are left untouched.\n *\n * The rewrite uses each user alias verbatim. If the user alias begins with\n * `src/`, that prefix is stripped because TypeScript-style `@/*` → `src/*`\n * mappings expect paths relative to `src`.\n */\nexport function rewriteImports(source: string, aliases: UiAliases): string {\n return source.replace(\n /(['\"])@\\/([a-z][a-z0-9-]*)(\\/[^'\"]*)?\\1/g,\n (full, quote: string, root: string, rest: string | undefined) => {\n const aliasKey = SOURCE_ROOT_TO_ALIAS_KEY[root];\n if (!aliasKey) return full;\n const alias = aliases[aliasKey];\n const normalized = aliasToImportPath(alias);\n // Flatten per-entry directory paths. In the source tree, cross-entry\n // references use `@/<root>/<entry-dir>/<file>` (e.g.\n // `@/components/skeleton/skeleton`), but after install files land flat\n // in the alias directory (`@/components/ui/skeleton`). Strip the\n // intermediate directory when rest has exactly two segments.\n const flatRest = flattenRestPath(rest);\n return `${quote}${normalized}${flatRest}${quote}`;\n },\n );\n}\n\n/**\n * Flatten a source-tree relative path for the installed (flat) layout.\n *\n * In the UI source tree, files live in per-entry directories:\n * `@/components/skeleton/skeleton` → rest = `/skeleton/skeleton`\n * After install, they are placed flat in the alias directory:\n * `@/components/ui/skeleton` → rest = `/skeleton`\n *\n * When rest has exactly two path segments (`/dir/file`), the first segment\n * (the entry directory) is stripped, leaving only the file reference.\n * Single-segment paths (e.g. `/cn`) pass through unchanged.\n */\nfunction flattenRestPath(rest: string | undefined): string {\n if (!rest) return '';\n // Split: \"/skeleton/skeleton\" → [\"\", \"skeleton\", \"skeleton\"]\n const segments = rest.split('/');\n if (segments.length === 3) {\n // Two real segments: /dir/file → /file\n return `/${segments[2]}`;\n }\n return rest;\n}\n\n/**\n * Convert an alias path (relative to the project root, e.g. `src/lib/utils`)\n * into an import-path prefix (`@/lib/utils`).\n *\n * Strips a leading `src/` so the path matches the convention of a `@/*` →\n * `src/*` tsconfig mapping. If the alias has a different prefix (for projects\n * that don't put code under `src/`), we keep it verbatim with `@/` prepended.\n */\nfunction aliasToImportPath(alias: string): string {\n const trimmed = alias.replace(/^\\.\\//, '').replace(/\\/$/, '');\n if (trimmed.startsWith('src/')) {\n return `@/${trimmed.slice('src/'.length)}`;\n }\n return `@/${trimmed}`;\n}\n","import type {\n InstalledManifest,\n InstalledResource,\n} from '@teamix-evo/registry';\nimport { loadUiData } from './ui-client.js';\nimport { installUiEntries } from './ui-installer.js';\nimport {\n readProjectConfig,\n writeProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\n\nconst DEFAULT_UI_PACKAGE = '@teamix-evo/ui';\n\nexport interface RunUiAddOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Entry ids to install (registry dependencies are resolved transitively). */\n ids: string[];\n /** When true, overwrite frozen entries that already exist on disk. */\n overwrite?: boolean;\n /** Override the ui package name (defaults to \"@teamix-evo/ui\"). */\n packageName?: string;\n /**\n * When true, allow installing entries that live in `manifest.deprecatedEntries`\n * (ADR 0028). Default: false — deprecated ids are treated as unknown and the\n * call errors with a hint pointing the user at the active replacement.\n */\n includeDeprecated?: boolean;\n}\n\nexport interface RunUiAddResult {\n packageName: string;\n /** Registered ids in install order (deps + requested). */\n orderedIds: string[];\n /** Number of files written. */\n written: number;\n /** Number of files skipped due to frozen + exists. */\n skipped: number;\n /** Aggregate npm dependencies of the installed entries. */\n npmDependencies: Record<string, string>;\n /** Per-file install records merged into the installed manifest. */\n resources: InstalledResource[];\n}\n\n/**\n * Programmatic equivalent of `teamix-evo ui add <ids...>`.\n *\n * Requires `packages.ui` to already exist in `.teamix-evo/config.json`\n * (i.e. {@link runUiInit} was called earlier).\n */\nexport async function runUiAdd(\n options: RunUiAddOptions,\n): Promise<RunUiAddResult> {\n const { projectRoot, ids, overwrite, includeDeprecated } = options;\n const packageName = options.packageName ?? DEFAULT_UI_PACKAGE;\n\n if (ids.length === 0) {\n throw new Error('At least one entry id must be provided.');\n }\n\n const config = await readProjectConfig(projectRoot);\n const uiCfg = config?.packages?.ui;\n if (!config || !uiCfg?.aliases) {\n throw new Error(\n 'UI not initialized. Run `runUiInit` (or `teamix-evo ui init`) first.',\n );\n }\n\n const { manifest, packageRoot } = await loadUiData(packageName);\n\n // Per ADR 0028: deprecated entries are archived in `deprecatedEntries`\n // and not exposed by default. When the caller opts in, we splice them\n // back into the active list so dependency resolution and install work\n // exactly as for active entries.\n const archived = manifest.deprecatedEntries ?? [];\n const archivedIds = new Set(archived.map((e) => e.id));\n const activeIds = new Set(manifest.entries.map((e) => e.id));\n\n const requestedDeprecated = ids.filter((id) => archivedIds.has(id));\n if (requestedDeprecated.length > 0 && !includeDeprecated) {\n const list = requestedDeprecated.map((s) => `\"${s}\"`).join(', ');\n throw new Error(\n `Refusing to install deprecated entr${\n requestedDeprecated.length === 1 ? 'y' : 'ies'\n } ${list}. ` +\n 'These entries are archived and not part of the active distribution (ADR 0028). ' +\n 'Pass `--include-deprecated` to override (e.g. for migration tooling).',\n );\n }\n\n const effectiveManifest = includeDeprecated\n ? { ...manifest, entries: [...manifest.entries, ...archived] }\n : manifest;\n\n const knownIds = new Set([\n ...activeIds,\n ...(includeDeprecated ? archivedIds : []),\n ]);\n const unknown = ids.filter((id) => !knownIds.has(id));\n if (unknown.length > 0) {\n throw new Error(\n `Unknown entry id(s): ${unknown\n .map((s) => `\"${s}\"`)\n .join(', ')}. Run \\`teamix-evo ui list\\` to see options.`,\n );\n }\n\n const result = await installUiEntries({\n projectRoot,\n manifest: effectiveManifest,\n packageRoot,\n aliases: uiCfg.aliases,\n requested: ids,\n skipExisting: !overwrite,\n });\n\n const installed: InstalledManifest = (await readInstalledManifest(\n projectRoot,\n )) ?? { schemaVersion: 1, installed: [] };\n\n const idx = installed.installed.findIndex((p) => p.package === packageName);\n const prior = idx >= 0 ? installed.installed[idx] : null;\n const mergedResources = mergeResources(\n prior?.resources ?? [],\n result.resources,\n );\n\n const entry = {\n package: packageName,\n variant: '_flat',\n version: manifest.version,\n installedAt: new Date().toISOString(),\n resources: mergedResources,\n };\n if (idx >= 0) installed.installed[idx] = entry;\n else installed.installed.push(entry);\n await writeInstalledManifest(projectRoot, installed);\n\n if (uiCfg.version !== manifest.version) {\n uiCfg.version = manifest.version;\n await writeProjectConfig(projectRoot, config);\n }\n\n return {\n packageName,\n orderedIds: result.orderedIds,\n written: result.written,\n skipped: result.skipped,\n npmDependencies: result.npmDependencies,\n resources: result.resources,\n };\n}\n\nfunction mergeResources<T extends { id: string }>(prior: T[], next: T[]): T[] {\n const merged = new Map<string, T>();\n for (const r of prior) merged.set(r.id, r);\n for (const r of next) merged.set(r.id, r);\n return Array.from(merged.values());\n}\n","import type { UiEntry } from '@teamix-evo/registry';\nimport { loadUiData } from './ui-client.js';\nimport { readInstalledManifest } from './state.js';\n\nconst DEFAULT_UI_PACKAGE = '@teamix-evo/ui';\n\nexport interface RunUiListOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** When true, only return entries that are already installed. */\n installedOnly?: boolean;\n /** Override the ui package name (defaults to \"@teamix-evo/ui\"). */\n packageName?: string;\n /**\n * When true, also include archived entries from `manifest.deprecatedEntries`\n * (ADR 0028). They are flagged with `deprecated: true` in the result.\n */\n includeDeprecated?: boolean;\n}\n\nexport interface UiEntryListItem {\n id: string;\n type: UiEntry['type'];\n description: string;\n installed: boolean;\n /** True when the entry comes from `manifest.deprecatedEntries` (ADR 0028). */\n deprecated: boolean;\n}\n\nexport interface RunUiListResult {\n packageName: string;\n /** Total number of entries declared by the package manifest. */\n total: number;\n /** Number of installed entries (based on the project's installed manifest). */\n installedCount: number;\n /** Filtered + decorated entries. */\n entries: UiEntryListItem[];\n}\n\n/**\n * Programmatic equivalent of `teamix-evo ui list`.\n *\n * Returns structured data; the CLI command formats it for terminal output.\n */\nexport async function runUiList(\n options: RunUiListOptions,\n): Promise<RunUiListResult> {\n const { projectRoot, installedOnly, includeDeprecated } = options;\n const packageName = options.packageName ?? DEFAULT_UI_PACKAGE;\n\n const { manifest } = await loadUiData(packageName);\n const installedManifest = await readInstalledManifest(projectRoot);\n\n const installedIds = new Set<string>();\n const uiPkg = installedManifest?.installed.find(\n (p) => p.package === packageName,\n );\n for (const r of uiPkg?.resources ?? []) {\n const colon = r.id.indexOf(':');\n installedIds.add(colon >= 0 ? r.id.slice(0, colon) : r.id);\n }\n\n const archived = manifest.deprecatedEntries ?? [];\n const pool = includeDeprecated\n ? [\n ...manifest.entries.map((e) => ({ entry: e, deprecated: false })),\n ...archived.map((e) => ({ entry: e, deprecated: true })),\n ]\n : manifest.entries.map((e) => ({ entry: e, deprecated: false }));\n\n const entries: UiEntryListItem[] = pool\n .filter(({ entry }) => !installedOnly || installedIds.has(entry.id))\n .map(({ entry, deprecated }) => ({\n id: entry.id,\n type: entry.type,\n description: entry.description,\n installed: installedIds.has(entry.id),\n deprecated,\n }));\n\n return {\n packageName,\n total: manifest.entries.length + (includeDeprecated ? archived.length : 0),\n installedCount: installedIds.size,\n entries,\n };\n}\n","/**\n * Programmatic install for variant-aware UI packages — biz-ui & templates.\n *\n * Per [ADR 0014](../../../../docs/adr/0014-ui-biz-ui-templates-tier.md), these\n * two packages share the variant-aware shape: top-level catalog + per-variant\n * manifest. The install logic is the same as `runUiAdd` (registry dependency\n * resolution + frozen-on-add + import rewrite) — only differences are:\n *\n * 1. The package source is `<pkg>/variants/<variant>/` rather than `<pkg>/`\n * 2. A `--variant` selector picks which variant to install from\n * 3. The installed manifest entry records `variant: \"<name>\"` rather than\n * `_flat`\n *\n * This module exposes a single shared implementation parametrized by\n * `packageName` (`@teamix-evo/biz-ui` or `@teamix-evo/templates`) and is\n * surfaced via `runBizUiAdd` / `runTemplatesAdd` thin wrappers.\n */\nimport * as path from 'node:path';\nimport { createRequire } from 'node:module';\nimport type {\n InstalledManifest,\n InstalledResource,\n UiEntry,\n UiPackageManifest,\n VariantUiPackageName,\n} from '@teamix-evo/registry';\nimport {\n loadUiPackageManifest,\n loadVariantUiPackageCatalog,\n loadVariantUiPackageManifest,\n} from '@teamix-evo/registry';\nimport { installUiEntries } from './ui-installer.js';\nimport {\n readProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\n\nconst require = createRequire(import.meta.url);\n\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\nexport interface RunVariantUiAddOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Variant id (e.g. `\"opentrek\"`). */\n variant: string;\n /** Entry ids to install. */\n ids: string[];\n /** When true, overwrite frozen entries that already exist on disk. */\n overwrite?: boolean;\n /** Override the package name. */\n packageName?: string;\n /**\n * Override resolution of the package root. When set, skips\n * `require.resolve(\"<packageName>/package.json\")`.\n */\n packageRoot?: string;\n}\n\nexport interface RunVariantUiAddResult {\n packageName: string;\n variant: string;\n orderedIds: string[];\n written: number;\n skipped: number;\n npmDependencies: Record<string, string>;\n resources: InstalledResource[];\n}\n\nasync function runVariantUiAdd(\n packageName: VariantUiPackageName,\n options: RunVariantUiAddOptions,\n): Promise<RunVariantUiAddResult> {\n const { projectRoot, variant, ids, overwrite } = options;\n const fullPackageName = options.packageName ?? `@teamix-evo/${packageName}`;\n\n if (ids.length === 0) {\n throw new Error('At least one entry id must be provided.');\n }\n\n const config = await readProjectConfig(projectRoot);\n const uiCfg = config?.packages?.ui;\n if (!config || !uiCfg?.aliases) {\n throw new Error(\n `UI not initialized. Run \\`teamix-evo ui init\\` first — \\`${packageName} add\\` writes into the same alias map (business / templates).`,\n );\n }\n\n const packageRoot =\n options.packageRoot ?? resolvePackageRoot(fullPackageName);\n\n // Validate that this variant exists in the catalog (clear error if not).\n const catalog = await loadVariantUiPackageCatalog(packageRoot);\n if (!catalog.variants.some((v) => v.name === variant)) {\n const known = catalog.variants.map((v) => v.name).join(', ');\n throw new Error(\n `Variant \"${variant}\" not found in ${fullPackageName}. Known variants: ${known}. Hint: \\`teamix-evo ${packageName} list-variants\\` shows all.`,\n );\n }\n\n // Load the per-variant manifest from packages/<pkg>/variants/<variant>/.\n const variantDir = path.join(packageRoot, 'variants', variant);\n const variantManifest = await loadVariantUiPackageManifest(variantDir);\n\n // Validate requested ids (must be defined in this variant package, not in ui)\n const knownIds = new Set(variantManifest.entries.map((e) => e.id));\n const unknown = ids.filter((id) => !knownIds.has(id));\n if (unknown.length > 0) {\n throw new Error(\n `Unknown entry id(s) in ${packageName}#${variant}: ${unknown\n .map((s) => `\"${s}\"`)\n .join(', ')}. Run \\`teamix-evo ${packageName} list-variants\\` to see this package's variants, or \\`teamix-evo ${packageName} list --variant ${variant}\\` for its entries.`,\n );\n }\n\n // Cross-package dependency resolution (fixes #22).\n // variant-aware entries (biz-ui / templates) reference @teamix-evo/ui entries\n // by id via `registryDependencies` (e.g. tenant-switcher → popover/button/cn).\n // Merge ui package's entries into the dep graph so the resolver can find\n // them. The installer's skipExisting=frozen guard means already-installed ui\n // entries are not rewritten.\n const uiPackageRoot = resolvePackageRoot('@teamix-evo/ui');\n const uiManifest = await loadUiPackageManifest(uiPackageRoot);\n\n // Resolve each entry's true package root for source file paths. Entries from\n // the variant package live under variantDir; entries from @teamix-evo/ui live\n // under uiPackageRoot.\n const entryPackageRoot = new Map<string, string>();\n const mergedEntries: UiEntry[] = [];\n for (const e of variantManifest.entries) {\n entryPackageRoot.set(e.id, variantDir);\n mergedEntries.push(e);\n }\n for (const e of uiManifest.entries) {\n // variant entry id wins over ui entry of same id (rare/illegal but safe).\n if (entryPackageRoot.has(e.id)) continue;\n entryPackageRoot.set(e.id, uiPackageRoot);\n mergedEntries.push(e);\n }\n\n const adaptedManifest: UiPackageManifest = {\n schemaVersion: 1,\n package: 'ui',\n version: variantManifest.version,\n engines: variantManifest.engines,\n entries: mergedEntries,\n };\n\n const result = await installUiEntries({\n projectRoot,\n manifest: adaptedManifest,\n packageRoot: variantDir, // default for variant entries\n entryPackageRoot, // ui entries resolve from uiPackageRoot\n aliases: uiCfg.aliases,\n requested: ids,\n skipExisting: !overwrite,\n });\n\n // Update installed manifest, keyed by (package, variant). Multiple variants\n // of the same package can co-exist (rare but legal).\n const installed: InstalledManifest = (await readInstalledManifest(\n projectRoot,\n )) ?? { schemaVersion: 1, installed: [] };\n\n const idx = installed.installed.findIndex(\n (p) => p.package === fullPackageName && p.variant === variant,\n );\n const prior = idx >= 0 ? installed.installed[idx] : null;\n const mergedResources = mergeResources(\n prior?.resources ?? [],\n result.resources,\n );\n\n const entry = {\n package: fullPackageName,\n variant,\n version: variantManifest.version,\n installedAt: new Date().toISOString(),\n resources: mergedResources,\n };\n if (idx >= 0) installed.installed[idx] = entry;\n else installed.installed.push(entry);\n await writeInstalledManifest(projectRoot, installed);\n\n return {\n packageName: fullPackageName,\n variant,\n orderedIds: result.orderedIds,\n written: result.written,\n skipped: result.skipped,\n npmDependencies: result.npmDependencies,\n resources: result.resources,\n };\n}\n\nfunction mergeResources<T extends { id: string }>(prior: T[], next: T[]): T[] {\n const merged = new Map<string, T>();\n for (const r of prior) merged.set(r.id, r);\n for (const r of next) merged.set(r.id, r);\n return Array.from(merged.values());\n}\n\n/** `teamix-evo biz-ui add <ids...> --variant <name>`. */\nexport async function runBizUiAdd(\n options: RunVariantUiAddOptions,\n): Promise<RunVariantUiAddResult> {\n return runVariantUiAdd('biz-ui', options);\n}\n\n/** `teamix-evo templates add <ids...> --variant <name>`. */\nexport async function runTemplatesAdd(\n options: RunVariantUiAddOptions,\n): Promise<RunVariantUiAddResult> {\n return runVariantUiAdd('templates', options);\n}\n\n// ─── List variants ───────────────────────────────────────────────────────────\n\nexport interface ListVariantUiResult {\n packageName: string;\n variants: Array<{\n name: string;\n displayName: string;\n version: string;\n description?: string;\n }>;\n}\n\nasync function listVariantUi(\n packageName: VariantUiPackageName,\n packageRoot?: string,\n): Promise<ListVariantUiResult> {\n const fullPackageName = `@teamix-evo/${packageName}`;\n const root = packageRoot ?? resolvePackageRoot(fullPackageName);\n const catalog = await loadVariantUiPackageCatalog(root);\n return {\n packageName: fullPackageName,\n variants: catalog.variants.map((v) => ({\n name: v.name,\n displayName: v.displayName,\n version: v.version,\n description: v.description,\n })),\n };\n}\n\nexport async function listBizUiVariants(\n packageRoot?: string,\n): Promise<ListVariantUiResult> {\n return listVariantUi('biz-ui', packageRoot);\n}\n\nexport async function listTemplatesVariants(\n packageRoot?: string,\n): Promise<ListVariantUiResult> {\n return listVariantUi('templates', packageRoot);\n}\n\n// ─── List entries inside a variant ───────────────────────────────────────────\n\nexport interface ListVariantUiEntriesResult {\n packageName: string;\n variant: string;\n entries: Array<{\n id: string;\n name: string;\n type: string;\n description?: string;\n registryDependencies: string[];\n }>;\n}\n\nasync function listVariantUiEntries(\n packageName: VariantUiPackageName,\n variant: string,\n packageRoot?: string,\n): Promise<ListVariantUiEntriesResult> {\n const fullPackageName = `@teamix-evo/${packageName}`;\n const root = packageRoot ?? resolvePackageRoot(fullPackageName);\n const catalog = await loadVariantUiPackageCatalog(root);\n if (!catalog.variants.some((v) => v.name === variant)) {\n const known = catalog.variants.map((v) => v.name).join(', ');\n throw new Error(\n `Variant \"${variant}\" not found in ${fullPackageName}. Known: ${known}.`,\n );\n }\n const variantDir = path.join(root, 'variants', variant);\n const variantManifest = await loadVariantUiPackageManifest(variantDir);\n return {\n packageName: fullPackageName,\n variant,\n entries: variantManifest.entries.map((e) => ({\n id: e.id,\n name: e.name,\n type: e.type,\n description: e.description,\n registryDependencies: e.registryDependencies ?? [],\n })),\n };\n}\n\nexport async function listBizUiEntries(\n variant: string,\n packageRoot?: string,\n): Promise<ListVariantUiEntriesResult> {\n return listVariantUiEntries('biz-ui', variant, packageRoot);\n}\n\nexport async function listTemplatesEntries(\n variant: string,\n packageRoot?: string,\n): Promise<ListVariantUiEntriesResult> {\n return listVariantUiEntries('templates', variant, packageRoot);\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { execa } from 'execa';\nimport {\n backupFile,\n fileExists,\n readFileOrNull,\n writeFileSafe,\n} from '../utils/fs.js';\nimport { logger } from '../utils/logger.js';\n\n// ─── Config file content ─────────────────────────────────────────────────────\n\nconst ESLINT_CONFIG_CONTENT = `/**\n * teamix-evo consumer ESLint preset — 9 token-discipline rules.\n * - Repo-wide: no-color-literal / no-arbitrary-tw-value / no-raw-color-scale /\n * no-large-radius / prefer-gap-over-space / no-manual-dark-classnames /\n * dialog-must-have-title (all error)\n * - src/components/ui/** only: no-relative-ui-import / icon-from-lucide (error)\n *\n * See ADR 0008 / docs/principles.md §P4.\n */\nimport consumerPreset from '@teamix-evo/eslint-config/presets/consumer';\n\nexport default [...consumerPreset];\n`;\n\nconst STYLELINT_CONFIG_CONTENT = `/** @type {import('stylelint').Config} */\nmodule.exports = {\n extends: ['@teamix-evo/stylelint-config/presets/consumer'],\n};\n`;\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * Phase 3.E lint conflict strategies (mirrors `init-conflicts.ts`).\n *\n * `merge` and `backup-overwrite` both back up the existing user file before\n * writing the teamix-evo template; `merge` additionally surfaces an AI-assist\n * hint so the manage / code skill can guide the user through merging custom\n * rules. `skip` keeps the user's file as-is and emits no template.\n */\nexport type LintConflictStrategy =\n | 'merge'\n | 'backup-overwrite'\n | 'skip'\n | 'overwrite';\n\nexport interface RunLintInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /**\n * Skip npm dependency installation. Used by the create scaffold where\n * dependencies are already declared in the template package.json and\n * installed in a later batch step.\n */\n skipInstall?: boolean;\n /**\n * Phase 3.E: strategy for handling existing ESLint config files.\n * Defaults to `'overwrite'` (legacy behaviour); the `init` orchestrator\n * passes the wizard-resolved value when consumer files are detected.\n */\n eslintStrategy?: LintConflictStrategy;\n /**\n * Phase 3.E: strategy for handling existing Stylelint config files.\n */\n stylelintStrategy?: LintConflictStrategy;\n /**\n * Phase 3.E: paths of existing ESLint configs (relative to projectRoot)\n * to back up. Empty when no consumer config was detected.\n */\n eslintExistingPaths?: string[];\n /**\n * Phase 3.E: paths of existing Stylelint configs (relative to projectRoot).\n */\n stylelintExistingPaths?: string[];\n}\n\nexport type RunLintInitResult =\n | {\n status: 'installed';\n eslint: boolean;\n stylelint: boolean;\n /** True when the user had a custom config and asked for AI-assisted merge. */\n eslintMergeRequested?: boolean;\n stylelintMergeRequested?: boolean;\n /** True when the strategy asked us to keep the user file untouched. */\n eslintSkipped?: boolean;\n stylelintSkipped?: boolean;\n /**\n * True when `package.json` was actually patched (lint / lint:css\n * scripts inserted). Powers the project-init change ledger so the\n * CLI does not report a phantom write when both scripts already\n * existed.\n */\n packageJsonPatched?: boolean;\n }\n | {\n status: 'already-initialized';\n };\n\n// ─── Lint dependencies ───────────────────────────────────────────────────────\n\nconst ESLINT_DEPS = [\n '@teamix-evo/eslint-config',\n 'eslint',\n '@typescript-eslint/parser',\n];\n\nconst STYLELINT_DEPS = ['@teamix-evo/stylelint-config', 'stylelint'];\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\n/**\n * Programmatic equivalent of `teamix-evo lint init`.\n *\n * Writes lint configuration files and optionally installs dependencies.\n * Idempotent: if both config files already exist, returns `already-initialized`.\n */\nexport async function runLintInit(\n options: RunLintInitOptions,\n): Promise<RunLintInitResult> {\n const {\n projectRoot,\n skipInstall,\n eslintStrategy = 'overwrite',\n stylelintStrategy = 'overwrite',\n eslintExistingPaths = [],\n stylelintExistingPaths = [],\n } = options;\n\n const eslintConfigPath = path.join(projectRoot, 'eslint.config.js');\n const stylelintConfigPath = path.join(projectRoot, 'stylelint.config.cjs');\n\n const eslintTemplateExists = await fileExists(eslintConfigPath);\n const stylelintTemplateExists = await fileExists(stylelintConfigPath);\n\n // Phase 3.E: a `skip` strategy only short-circuits when the *consumer*\n // already has a config. Without it we still need to write our template.\n const eslintSkipRequested =\n eslintStrategy === 'skip' && eslintExistingPaths.length > 0;\n const stylelintSkipRequested =\n stylelintStrategy === 'skip' && stylelintExistingPaths.length > 0;\n\n const eslintNeedsWrite = !eslintTemplateExists && !eslintSkipRequested;\n const stylelintNeedsWrite =\n !stylelintTemplateExists && !stylelintSkipRequested;\n\n if (!eslintNeedsWrite && !stylelintNeedsWrite) {\n return { status: 'already-initialized' };\n }\n\n // ─── Install dependencies ──────────────────────────────────────────────\n if (!skipInstall) {\n const depsToInstall = [\n ...(eslintNeedsWrite ? ESLINT_DEPS : []),\n ...(stylelintNeedsWrite ? STYLELINT_DEPS : []),\n ];\n\n if (depsToInstall.length > 0) {\n const pm = detectPm(projectRoot);\n const args =\n pm === 'yarn'\n ? ['add', '--dev', ...depsToInstall]\n : pm === 'pnpm'\n ? ['add', '-D', ...depsToInstall]\n : ['install', '--save-dev', ...depsToInstall];\n\n logger.info(`Installing lint deps via ${pm}...`);\n await execa(pm, args, { cwd: projectRoot, stdio: 'inherit' });\n }\n }\n\n // ─── Phase 3.E: back up consumer configs before writing template ───────\n // Phase 1.A2 — `overwrite` strategy still demands a `.bak` so the user\n // can recover the original file. Only `eslintNeedsWrite` /\n // `stylelintNeedsWrite` gates the operation (a `skip`d file is left\n // untouched, so no backup is needed).\n if (eslintNeedsWrite && eslintExistingPaths.length > 0) {\n for (const rel of eslintExistingPaths) {\n await backupFile(path.join(projectRoot, rel), projectRoot);\n }\n }\n if (stylelintNeedsWrite && stylelintExistingPaths.length > 0) {\n for (const rel of stylelintExistingPaths) {\n await backupFile(path.join(projectRoot, rel), projectRoot);\n }\n }\n\n // ─── Write config files ────────────────────────────────────────────────\n let wroteEslint = false;\n let wroteStylelint = false;\n\n if (eslintNeedsWrite) {\n await writeFileSafe(eslintConfigPath, ESLINT_CONFIG_CONTENT);\n logger.debug(`Wrote eslint.config.js → ${eslintConfigPath}`);\n wroteEslint = true;\n }\n\n if (stylelintNeedsWrite) {\n await writeFileSafe(stylelintConfigPath, STYLELINT_CONFIG_CONTENT);\n logger.debug(`Wrote stylelint.config.cjs → ${stylelintConfigPath}`);\n wroteStylelint = true;\n }\n\n // ─── Patch package.json scripts ────────────────────────────────────────\n // Phase 1.A2: package.json is a high-value user file — back it up before\n // we mutate `scripts.lint` / `scripts['lint:css']` so the user can revert\n // the patch without git if needed.\n const packageJsonPatched = await patchPackageJsonScripts(projectRoot);\n\n return {\n status: 'installed',\n eslint: wroteEslint,\n stylelint: wroteStylelint,\n eslintMergeRequested:\n wroteEslint &&\n eslintStrategy === 'merge' &&\n eslintExistingPaths.length > 0,\n stylelintMergeRequested:\n wroteStylelint &&\n stylelintStrategy === 'merge' &&\n stylelintExistingPaths.length > 0,\n eslintSkipped: eslintSkipRequested,\n stylelintSkipped: stylelintSkipRequested,\n packageJsonPatched,\n };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/**\n * Detect package manager from lockfile presence.\n */\nfunction detectPm(projectRoot: string): 'pnpm' | 'yarn' | 'npm' {\n if (fs.existsSync(path.join(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm';\n if (fs.existsSync(path.join(projectRoot, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\n/**\n * Add lint scripts to package.json if they don't already exist.\n *\n * Returns `true` when at least one of `scripts.lint` / `scripts['lint:css']`\n * was inserted (so the caller can decide whether to surface a `package.json`\n * change in the project-init ledger). Returns `false` when both scripts\n * already existed or when `package.json` is missing/unparseable.\n */\nasync function patchPackageJsonScripts(projectRoot: string): Promise<boolean> {\n const pkgPath = path.join(projectRoot, 'package.json');\n const raw = await readFileOrNull(pkgPath);\n if (!raw) return false;\n\n let pkg: Record<string, unknown>;\n try {\n pkg = JSON.parse(raw);\n } catch {\n return false;\n }\n\n const scripts = (pkg.scripts ?? {}) as Record<string, string>;\n let changed = false;\n\n if (!scripts.lint) {\n scripts.lint = 'eslint src/';\n changed = true;\n }\n if (!scripts['lint:css']) {\n scripts['lint:css'] = \"stylelint 'src/**/*.css'\";\n changed = true;\n }\n\n if (changed) {\n // Backup user package.json before patching scripts (Phase 1.A2).\n await backupFile(pkgPath, projectRoot);\n pkg.scripts = scripts;\n await writeFileSafe(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n logger.debug('Patched package.json scripts with lint / lint:css');\n }\n return changed;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { hasManagedRegion, replaceManagedRegion } from '@teamix-evo/registry';\nimport { backupFile, fileExists, readFileOrNull } from '../utils/fs.js';\nimport { getSkillsSourceDir } from './state.js';\n\n/**\n * Generate `<projectRoot>/AGENTS.md` as a skill-trigger fallback (ADR 0038).\n *\n * The file is **regenerable**: it consolidates TRIGGER / SKIP excerpts from\n * each installed SKILL.md frontmatter description into one terse index, so\n * AGENTS.md-aware IDEs (Codex / Cursor / Claude Code / Qoder) preheat the\n * skill activation conditions even when the user prompt does not directly\n * hit the description-based trigger.\n *\n * Out of scope (per ADR 0038):\n * - Does NOT copy skill body / rules / patterns — those stay in the skill.\n * - Does NOT include `teamix-evo-manage` (entry skill, global scope, ADR 0033).\n *\n * Lifted from `create-teamix-evo` (v0.5) into `teamix-evo/core` so both\n * `npm create teamix-evo` (scaffold path) and `teamix-evo init` (existing-\n * project path, ADR 0019 task #5) emit identical AGENTS.md output.\n *\n * @module teamix-evo/core/agents-md\n */\n\nexport interface RunGenerateAgentsMdOptions {\n /** Absolute path to the consumer project root. */\n projectRoot: string;\n /** Tokens / skills variant (e.g. \"opentrek\"). Used for header context. */\n variant: string;\n /**\n * Skill ids whose `<projectRoot>/.teamix-evo/skills/<id>/SKILL.md` should be\n * indexed. Caller is responsible for filtering out global-only skills\n * (e.g. `teamix-evo-manage`).\n */\n skillIds: string[];\n /**\n * Reconciliation mode (Phase 2.B):\n * - `'overwrite'` (default): always rewrite the full file. Pre-existing\n * content is backed up and discarded.\n * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed\n * region. When the consumer file lacks the region, prepend a fresh\n * managed block ahead of the user's content (auto-adopt). The user's\n * non-managed sections are preserved.\n *\n * In both modes, an existing file is backed up under\n * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before any mutation.\n */\n mode?: 'overwrite' | 'merge-managed';\n}\n\nexport interface RunGenerateAgentsMdResult {\n /** Absolute path of the written `AGENTS.md`. */\n path: string;\n /** Number of skill sections rendered (missing SKILL.md degradations are still counted). */\n skillCount: number;\n /** Skill ids whose SKILL.md could not be read (rendered as degraded section). */\n missingSkillIds: string[];\n /**\n * True when an existing AGENTS.md was backed up under\n * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before being overwritten\n * (Phase 1.A2 — full backup strategy).\n */\n backedUp: boolean;\n /**\n * Outcome of the merge step (Phase 2.B):\n * - `'created'`: no AGENTS.md existed; wrote a fresh full template.\n * - `'overwritten'`: existed but mode='overwrite' — full rewrite.\n * - `'managed-replaced'`: mode='merge-managed' and the consumer file\n * already had the `teamix-evo-skills` managed region; only that region\n * was rewritten. User content outside is preserved.\n * - `'managed-prepended'`: mode='merge-managed' but the consumer file\n * did not yet have the managed region; a fresh block was inserted at\n * the top, with the existing user content kept below.\n */\n merge: 'created' | 'overwritten' | 'managed-replaced' | 'managed-prepended';\n}\n\n/** Region id wrapping the auto-generated skill index. */\nexport const AGENTS_MD_MANAGED_ID = 'teamix-evo-skills';\n\ninterface SkillDescriptionParts {\n /** First non-empty line(s) of `description` (the capability statement). */\n capability: string;\n trigger: string | null;\n skip: string | null;\n coordinates: string | null;\n}\n\n/**\n * Generate and write the `AGENTS.md` file.\n *\n * Phase 2.B — reconciliation modes:\n * - `'overwrite'` (default): regenerable behaviour, full rewrite.\n * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed region\n * so user-authored sections (project-specific guidance, design tokens,\n * prompts) are never clobbered.\n *\n * Existing files are always backed up under `.teamix-evo/.backups/` before\n * mutation (ADR 0019 §2, Phase 1.A2).\n */\nexport async function runGenerateAgentsMd(\n options: RunGenerateAgentsMdOptions,\n): Promise<RunGenerateAgentsMdResult> {\n const { projectRoot, variant, skillIds } = options;\n const mode = options.mode ?? 'overwrite';\n\n // Stable order: design → code → others (alphabetical within each bucket).\n const ordered = [...skillIds].sort(\n (a, b) => bucketRank(a) - bucketRank(b) || a.localeCompare(b),\n );\n\n const sections: string[] = [];\n const missingSkillIds: string[] = [];\n for (const id of ordered) {\n const { section, missing } = await renderSkillSection(projectRoot, id);\n sections.push(section);\n if (missing) missingSkillIds.push(id);\n }\n\n const target = path.join(projectRoot, 'AGENTS.md');\n const targetExists = await fileExists(target);\n const fullTemplate = renderAgentsMd({ variant, sections });\n const managedBody = renderManagedBlockBody({ variant, sections });\n\n let outputContent: string;\n let merge: RunGenerateAgentsMdResult['merge'];\n\n if (!targetExists) {\n outputContent = fullTemplate;\n merge = 'created';\n } else {\n // Backup before any mutation — truthful even if downstream throws.\n await backupFile(target, projectRoot);\n if (mode === 'merge-managed') {\n const existing = (await readFileOrNull(target)) ?? '';\n if (hasManagedRegion(existing, AGENTS_MD_MANAGED_ID)) {\n outputContent = replaceManagedRegion(\n existing,\n AGENTS_MD_MANAGED_ID,\n managedBody,\n );\n merge = 'managed-replaced';\n } else {\n // Auto-adopt: place the managed block at the top so AGENTS.md-aware\n // IDEs preheat skill triggers first, then keep the user's prior\n // content as a non-managed tail. A trailing precedence notice goes\n // immediately after the managed block.\n const wrapped = wrapManagedBlock(managedBody);\n outputContent = `${wrapped}\\n\\n${PRECEDENCE_NOTICE}\\n\\n${existing.trimStart()}`;\n merge = 'managed-prepended';\n }\n } else {\n // overwrite — historical default.\n outputContent = fullTemplate;\n merge = 'overwritten';\n }\n }\n\n await fs.writeFile(target, outputContent, 'utf8');\n return {\n path: target,\n skillCount: ordered.length,\n missingSkillIds,\n backedUp: targetExists,\n merge,\n };\n}\n\nfunction bucketRank(id: string): number {\n if (id.startsWith('teamix-evo-design-')) return 0;\n if (id.startsWith('teamix-evo-code-')) return 1;\n return 2;\n}\n\nasync function renderSkillSection(\n projectRoot: string,\n skillId: string,\n): Promise<{ section: string; missing: boolean }> {\n const skillPath = path.join(\n getSkillsSourceDir(projectRoot, skillId),\n 'SKILL.md',\n );\n const lines: string[] = [];\n lines.push(`### ${skillId}`);\n let parts: SkillDescriptionParts | null = null;\n let missing = false;\n try {\n const raw = await fs.readFile(skillPath, 'utf8');\n parts = extractDescriptionParts(raw);\n } catch {\n // SKILL.md missing — degrade gracefully, AI still gets the location hint.\n missing = true;\n }\n\n if (parts?.capability) {\n lines.push(`- ${parts.capability}`);\n }\n lines.push(\n `- **TRIGGER**: ${\n parts?.trigger ?? '未配置触发条件,需手动激活该 skill。'\n }`,\n );\n lines.push(\n `- **SKIP**: ${parts?.skip ?? '未配置跳过条件,按 TRIGGER 兜底判定。'}`,\n );\n if (parts?.coordinates) {\n lines.push(`- **Coordinates with**: ${parts.coordinates}`);\n }\n lines.push(`- **位置**: \\`.teamix-evo/skills-source/${skillId}/SKILL.md\\``);\n return { section: lines.join('\\n'), missing };\n}\n\nfunction renderAgentsMd(args: { variant: string; sections: string[] }): string {\n const { variant, sections } = args;\n const managedBody = renderManagedBlockBody({ variant, sections });\n const wrapped = wrapManagedBlock(managedBody);\n return `${wrapped}\\n\\n${PRECEDENCE_NOTICE}\\n`;\n}\n\n/**\n * Body of the `teamix-evo-skills` managed region (no enclosing markers).\n * Phase 2.B — isolated so {@link runGenerateAgentsMd} can substitute it via\n * `replaceManagedRegion` when reconciling against a user-edited AGENTS.md.\n *\n * Exported so external tools (e.g. the `teamix-evo-manage` skill) can render\n * a preview without depending on the file write path.\n */\nexport function renderManagedBlockBody(args: {\n variant: string;\n sections: string[];\n}): string {\n const { variant, sections } = args;\n const skillBlock =\n sections.length > 0\n ? sections.join('\\n\\n')\n : '_(本工程未装配工程级 skill。)_';\n return `# AGENTS.md\n\n> 本工程已装配 Teamix Evo AI skills。AI 助手在以下场景下**必须先读对应 skill** 再动手。\n> 本文件由 \\`teamix-evo init\\` / \\`create-teamix-evo\\` 自动生成(regenerable,[ADR 0038](https://github.com/teamix-evo/teamix-evo/blob/main/docs/adr/0038-create-agents-md-skill-trigger-fallback.md)),刷新方式见底部。\n\n## 已装 Skills(variant: ${variant})\n\n${skillBlock}\n\n## 触发兜底规则\n\n- 写新 \\`.tsx\\` / \\`.ts\\` 前,对照上述 TRIGGER 判定是否命中\n- 命中则先读对应 \\`SKILL.md\\`,再动手;二者同时命中则两个都读\n- 模糊场景:先按 SKIP 反向排除,剩余唯一 skill 即为入口\n- 生命周期命令(\\`init\\` / \\`update\\` / \\`add\\`)走 \\`teamix-evo-manage\\`(全局 skill,本文件不列)\n\n> 刷新本文件:\\`npx teamix-evo skills add\\` 或重跑 \\`npm create teamix-evo\\` / \\`teamix-evo init\\`。`;\n}\n\nfunction wrapManagedBlock(body: string): string {\n return `<!-- teamix-evo:managed:start id=\"${AGENTS_MD_MANAGED_ID}\" -->\\n${body}\\n<!-- teamix-evo:managed:end id=\"${AGENTS_MD_MANAGED_ID}\" -->`;\n}\n\n/**\n * Footer notice (Phase 2.B): when AGENTS.md hosts both managed and\n * user-authored sections, the managed Skills index wins on conflict.\n */\nconst PRECEDENCE_NOTICE = `<!-- teamix-evo:precedence -->\n> 冲突以上方的 **Skills** 索引为准(上游路径与 TRIGGER/SKIP 契约);项目特有的人工细则请写在本处以下、不要覆盖上方 managed 区域。`;\n\n// ─── frontmatter parsing ──────────────────────────────────────────────────────\n\n/**\n * Parse a SKILL.md frontmatter description into capability / TRIGGER / SKIP /\n * Coordinates parts.\n *\n * Why hand-rolled (no gray-matter): we only need the `description: |` block.\n * The full YAML grammar is overkill and adds a runtime dep to a CLI / scaffold\n * tool that should stay zero-cost. ADR 0015 keeps frontmatter shape stable.\n */\nexport function extractDescriptionParts(\n fileContent: string,\n): SkillDescriptionParts | null {\n const description = extractDescriptionBlock(fileContent);\n if (description == null) return null;\n\n // Capability = first line that is not a TRIGGER/SKIP/Coordinates marker.\n const allLines = description\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n let capability = '';\n for (const line of allLines) {\n if (/^(TRIGGER when:|SKIP:|Coordinates with:)/i.test(line)) break;\n capability = capability ? `${capability} ${line}` : line;\n }\n\n return {\n capability: capability.trim(),\n trigger: extractSection(description, 'TRIGGER when:'),\n skip: extractSection(description, 'SKIP:'),\n coordinates: extractSection(description, 'Coordinates with:'),\n };\n}\n\n/**\n * Extract the `description: |` (or `description: >`) block body. Returns null\n * if the field is missing or not a literal/folded block.\n */\nfunction extractDescriptionBlock(fileContent: string): string | null {\n const lines = fileContent.split('\\n');\n\n // Find frontmatter range: first `---`, then matching `---`.\n if (lines[0]?.trim() !== '---') return null;\n let endIdx = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i]?.trim() === '---') {\n endIdx = i;\n break;\n }\n }\n if (endIdx === -1) return null;\n const fmLines = lines.slice(1, endIdx);\n\n // Locate `description:` key.\n let startIdx = -1;\n let inlineValue: string | null = null;\n let blockMode: 'literal' | 'folded' | 'inline' = 'inline';\n for (let i = 0; i < fmLines.length; i++) {\n const m = fmLines[i]?.match(/^description:\\s*(\\|[+-]?|>[+-]?)?\\s*(.*)$/);\n if (m) {\n startIdx = i;\n const indicator = (m[1] ?? '').trim();\n const rest = m[2] ?? '';\n if (indicator.startsWith('|')) blockMode = 'literal';\n else if (indicator.startsWith('>')) blockMode = 'folded';\n else {\n blockMode = 'inline';\n inlineValue = rest;\n }\n break;\n }\n }\n if (startIdx === -1) return null;\n\n if (blockMode === 'inline') {\n return inlineValue ?? '';\n }\n\n // Block mode: collect indented continuation lines.\n const body: string[] = [];\n // Detect the block indent from the first non-empty continuation line.\n let blockIndent = -1;\n for (let i = startIdx + 1; i < fmLines.length; i++) {\n const line = fmLines[i] ?? '';\n if (line.trim() === '') {\n body.push('');\n continue;\n }\n const indentMatch = line.match(/^(\\s+)/);\n const indent = indentMatch ? indentMatch[1]!.length : 0;\n if (indent === 0) break; // back to top-level key\n if (blockIndent === -1) blockIndent = indent;\n if (indent < blockIndent) break;\n body.push(line.slice(blockIndent));\n }\n // Trim trailing empty lines.\n while (body.length > 0 && body[body.length - 1] === '') body.pop();\n return body.join('\\n');\n}\n\n/**\n * Extract the body of a description sub-section starting with the given\n * marker (e.g. \"TRIGGER when:\"). Stops at the next known marker or end of\n * description. Returns the stripped one-line summary (sub-section text with\n * internal newlines collapsed to spaces).\n */\nfunction extractSection(description: string, marker: string): string | null {\n const markers = ['TRIGGER when:', 'SKIP:', 'Coordinates with:'];\n const lines = description.split('\\n');\n let inSection = false;\n const collected: string[] = [];\n for (const line of lines) {\n const trimmed = line.trim();\n const startsWithMarker = trimmed\n .toLowerCase()\n .startsWith(marker.toLowerCase());\n if (!inSection && startsWithMarker) {\n inSection = true;\n collected.push(trimmed.slice(marker.length).trim());\n continue;\n }\n if (inSection) {\n const hitNextMarker = markers.some(\n (m) =>\n m !== marker && trimmed.toLowerCase().startsWith(m.toLowerCase()),\n );\n if (hitNextMarker) break;\n if (trimmed === '') {\n // Allow blank line within section but stop on second consecutive blank.\n if (collected[collected.length - 1] === '') break;\n collected.push('');\n continue;\n }\n collected.push(trimmed);\n }\n }\n if (!inSection) return null;\n const joined = collected\n .filter((l) => l !== '')\n .join(' ')\n .replace(/\\s+/g, ' ')\n .trim();\n return joined || null;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { fileExists } from '../utils/fs.js';\nimport { getTeamixDir } from './state.js';\n\n/**\n * Three branches of `teamix-evo init` decision tree (ADR 0019 D1).\n *\n * - `empty` : 空目录或仅含可忽略文件 → 推荐用户走 `npm create teamix-evo`(完整版)\n * - `teamix-evo-installed`: 已存在 `.teamix-evo/` → 推荐 `teamix-evo update` / 卸载流程\n * - `non-teamix-evo` : 已有非 teamix-evo 工程 → 走 `teamix-evo init` 普通版接入\n */\nexport type ProjectState = 'empty' | 'teamix-evo-installed' | 'non-teamix-evo';\n\nexport interface ProjectStateReport {\n /** Decision-tree branch the caller should take. */\n state: ProjectState;\n /** Absolute path that was inspected. */\n cwd: string;\n /** Whether `.teamix-evo/` exists at `cwd`. */\n hasTeamixDir: boolean;\n /** Whether `package.json` exists at `cwd`. */\n hasPackageJson: boolean;\n /**\n * Up to 20 entries (relative to `cwd`) that caused us to consider the\n * directory non-empty. Useful for explaining the decision to humans.\n */\n significantEntries: string[];\n}\n\n/**\n * Filenames that should NOT cause us to flip out of the `empty` branch.\n *\n * Mirrors the convention shared by `create-next-app`, `nx init`, and\n * `npm init` — these are typical files added by `git init`, an editor,\n * or the OS, not project content.\n */\nconst IGNORED_TOP_LEVEL = new Set<string>([\n '.git',\n '.gitignore',\n '.gitattributes',\n '.gitkeep',\n '.DS_Store',\n 'Thumbs.db',\n '.idea',\n '.vscode',\n '.qoder',\n '.claude',\n 'README.md',\n 'README',\n 'README.txt',\n 'LICENSE',\n 'LICENSE.md',\n 'LICENSE.txt',\n]);\n\n/**\n * Inspect `cwd` and decide which branch of the `teamix-evo init` decision\n * tree applies. Pure read-only — never mutates the filesystem.\n *\n * Resolution order (first match wins):\n * 1. `.teamix-evo/` exists → `teamix-evo-installed`\n * 2. cwd missing OR all entries are in the IGNORED_TOP_LEVEL set\n * → `empty`\n * 3. otherwise → `non-teamix-evo`\n */\nexport async function detectProjectState(\n cwd: string,\n): Promise<ProjectStateReport> {\n const absCwd = path.resolve(cwd);\n\n const teamixDir = getTeamixDir(absCwd);\n const hasTeamixDir = await fileExists(teamixDir);\n if (hasTeamixDir) {\n return {\n state: 'teamix-evo-installed',\n cwd: absCwd,\n hasTeamixDir: true,\n hasPackageJson: await fileExists(path.join(absCwd, 'package.json')),\n significantEntries: [],\n };\n }\n\n let entries: string[];\n try {\n entries = await fs.readdir(absCwd);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n // Caller pointed us at a directory that doesn't exist yet — treat as\n // empty so `init` can create it (mirrors `npm create` behavior).\n return {\n state: 'empty',\n cwd: absCwd,\n hasTeamixDir: false,\n hasPackageJson: false,\n significantEntries: [],\n };\n }\n throw err;\n }\n\n const significant = entries.filter((e) => !IGNORED_TOP_LEVEL.has(e));\n const hasPackageJson = entries.includes('package.json');\n\n if (significant.length === 0) {\n return {\n state: 'empty',\n cwd: absCwd,\n hasTeamixDir: false,\n hasPackageJson: false,\n significantEntries: [],\n };\n }\n\n return {\n state: 'non-teamix-evo',\n cwd: absCwd,\n hasTeamixDir: false,\n hasPackageJson,\n significantEntries: significant.slice(0, 20).sort(),\n };\n}\n","import * as crypto from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { fileExists, readFileOrNull } from '../utils/fs.js';\n\n/**\n * The 8 categories of consumer-side files that `teamix-evo init` may\n * conflict with when running against a non-teamix-evo project.\n *\n * See ADR 0019 D1 task #5 — these are the only files we mutate at\n * `init` time, so they're the only ones we ask the user about.\n */\nexport type ConflictKey =\n | 'agents-md'\n | 'components-json'\n | 'tailwind-config'\n | 'tokens'\n | 'index-css'\n | 'shadcn-source'\n | 'eslint-config'\n | 'stylelint-config';\n\n/** Strategy options per conflict category. */\nexport type ConflictStrategy =\n // agents-md\n | 'overwrite'\n | 'merge-managed'\n | 'skip'\n // components-json\n | 'diff-prompt'\n // tailwind-config\n | 'backup-overwrite'\n // tokens\n | 'migrate'\n | 'coexist'\n // index-css\n | 'append'\n // shadcn-source\n | 'skip-existing'\n | 'per-file-prompt'\n // eslint-config / stylelint-config (Phase 3.E)\n | 'merge';\n\nexport interface ConflictItem {\n /** Stable id for the category. */\n key: ConflictKey;\n /** True if at least one path in `paths` matched on disk. */\n exists: boolean;\n /**\n * Project-relative paths that matched. Empty when `exists === false`.\n * For `shadcn-source`, may contain a directory path (with trailing `/`).\n */\n paths: string[];\n /** sha256 fingerprint of (sorted) matched contents. Omitted for directories or when nothing matched. */\n fingerprint?: string;\n /** Default strategy presented to the user. */\n recommendedStrategy: ConflictStrategy;\n /** All allowed strategies for this category, in display order. */\n availableStrategies: ConflictStrategy[];\n /** Category-specific metadata (e.g. detected tailwind major version). */\n meta?: Record<string, unknown>;\n}\n\nexport interface ConflictReport {\n cwd: string;\n /** Always 8 items, ordered by ConflictKey enumeration above. */\n items: ConflictItem[];\n /** True if any item has `exists === true`. */\n hasAnyConflict: boolean;\n}\n\n// ─── Path candidates per category ────────────────────────────────────────────\n\nconst TAILWIND_CONFIG_CANDIDATES = [\n 'tailwind.config.ts',\n 'tailwind.config.js',\n 'tailwind.config.cjs',\n 'tailwind.config.mjs',\n];\n\nconst TOKENS_FILE_CANDIDATES = [\n 'src/design-tokens.css',\n 'src/styles/design-tokens.css',\n 'src/styles/tokens.css',\n];\n\nconst TOKENS_DIR_CANDIDATES = ['tokens'];\n\nconst INDEX_CSS_CANDIDATES = [\n 'src/index.css',\n 'src/main.css',\n 'src/app.css',\n 'src/styles/index.css',\n 'src/styles/globals.css',\n];\n\nconst SHADCN_FILE_CANDIDATES = ['src/lib/utils.ts'];\nconst SHADCN_DIR_CANDIDATES = ['src/components/ui'];\n\n// Phase 3.E: 8 ESLint candidates (legacy `.eslintrc.*` + flat `eslint.config.*`)\nconst ESLINT_CONFIG_CANDIDATES = [\n '.eslintrc.cjs',\n '.eslintrc.js',\n '.eslintrc.json',\n '.eslintrc.yml',\n 'eslint.config.js',\n 'eslint.config.cjs',\n 'eslint.config.mjs',\n 'eslint.config.ts',\n];\n\n// Phase 3.E: 8 Stylelint candidates (legacy `.stylelintrc.*` + flat `stylelint.config.*`)\nconst STYLELINT_CONFIG_CANDIDATES = [\n '.stylelintrc.cjs',\n '.stylelintrc.js',\n '.stylelintrc.json',\n '.stylelintrc.yml',\n 'stylelint.config.cjs',\n 'stylelint.config.js',\n 'stylelint.config.mjs',\n 'stylelint.config.ts',\n];\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nasync function isDir(target: string): Promise<boolean> {\n try {\n const stat = await fs.stat(target);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function dirHasContent(target: string): Promise<boolean> {\n try {\n const entries = await fs.readdir(target);\n return entries.length > 0;\n } catch {\n return false;\n }\n}\n\n/** Hash of UTF-8 string content; truncate to 16 chars for log readability. */\nfunction fingerprint(parts: string[]): string {\n const hash = crypto.createHash('sha256');\n for (const p of [...parts].sort()) hash.update(p);\n return `sha256:${hash.digest('hex').slice(0, 16)}`;\n}\n\ninterface PackageJsonShape {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJsonShape | null> {\n const raw = await readFileOrNull(path.join(cwd, 'package.json'));\n if (raw === null) return null;\n try {\n return JSON.parse(raw) as PackageJsonShape;\n } catch {\n return null;\n }\n}\n\n/**\n * Detect tailwind major version from package.json.\n * Returns 4 / 3 / null. We trust dependencies + devDependencies.\n */\nfunction detectTailwindMajor(pkg: PackageJsonShape | null): 3 | 4 | null {\n if (!pkg) return null;\n const v =\n pkg.dependencies?.tailwindcss ?? pkg.devDependencies?.tailwindcss ?? null;\n if (!v) return null;\n // Accept \"^4.0.0\" / \"~4.2.2\" / \"4.x\" / \"next\" → conservative: parse leading digit\n const m = /(\\d+)/.exec(v);\n if (!m) return null;\n const major = Number.parseInt(m[1]!, 10);\n if (major === 3) return 3;\n if (major === 4) return 4;\n return null;\n}\n\n// ─── Per-category detectors ──────────────────────────────────────────────────\n\nasync function detectAgentsMd(cwd: string): Promise<ConflictItem> {\n const target = path.join(cwd, 'AGENTS.md');\n const content = await readFileOrNull(target);\n const exists = content !== null;\n return {\n key: 'agents-md',\n exists,\n paths: exists ? ['AGENTS.md'] : [],\n fingerprint: exists ? fingerprint([content!]) : undefined,\n recommendedStrategy: exists ? 'merge-managed' : 'overwrite',\n availableStrategies: ['merge-managed', 'overwrite', 'skip'],\n };\n}\n\nasync function detectComponentsJson(cwd: string): Promise<ConflictItem> {\n const target = path.join(cwd, 'components.json');\n const content = await readFileOrNull(target);\n const exists = content !== null;\n return {\n key: 'components-json',\n exists,\n paths: exists ? ['components.json'] : [],\n fingerprint: exists ? fingerprint([content!]) : undefined,\n recommendedStrategy: exists ? 'diff-prompt' : 'overwrite',\n availableStrategies: ['diff-prompt', 'overwrite', 'skip'],\n };\n}\n\nasync function detectTailwindConfig(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of TAILWIND_CONFIG_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const pkg = await readPackageJson(cwd);\n const tailwindMajor = detectTailwindMajor(pkg);\n const exists = matched.length > 0;\n return {\n key: 'tailwind-config',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'backup-overwrite' : 'overwrite',\n availableStrategies: ['backup-overwrite', 'overwrite', 'skip'],\n meta: { tailwindMajor },\n };\n}\n\nasync function detectTokens(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of TOKENS_FILE_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n for (const rel of TOKENS_DIR_CANDIDATES) {\n const abs = path.join(cwd, rel);\n if ((await isDir(abs)) && (await dirHasContent(abs))) {\n matched.push(`${rel}/`);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'tokens',\n exists,\n paths: matched,\n fingerprint: contents.length > 0 ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'migrate' : 'overwrite',\n availableStrategies: ['migrate', 'coexist', 'overwrite', 'skip'],\n };\n}\n\nasync function detectIndexCss(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of INDEX_CSS_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'index-css',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'append' : 'overwrite',\n availableStrategies: ['append', 'diff-prompt', 'overwrite', 'skip'],\n };\n}\n\nasync function detectShadcnSource(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n for (const rel of SHADCN_FILE_CANDIDATES) {\n if (await fileExists(path.join(cwd, rel))) matched.push(rel);\n }\n for (const rel of SHADCN_DIR_CANDIDATES) {\n const abs = path.join(cwd, rel);\n if ((await isDir(abs)) && (await dirHasContent(abs))) {\n matched.push(`${rel}/`);\n }\n }\n // For shadcn dir, count component files for meta.\n let componentCount = 0;\n try {\n const uiDir = path.join(cwd, 'src/components/ui');\n if (await isDir(uiDir)) {\n const entries = await fs.readdir(uiDir);\n componentCount = entries.filter(\n (e) => e.endsWith('.tsx') || e.endsWith('.ts'),\n ).length;\n }\n } catch {\n // ignore\n }\n const exists = matched.length > 0;\n return {\n key: 'shadcn-source',\n exists,\n paths: matched,\n recommendedStrategy: exists ? 'skip-existing' : 'overwrite',\n availableStrategies: ['skip-existing', 'per-file-prompt', 'overwrite'],\n meta: { componentCount },\n };\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Inspect `cwd` for the 8 categories of files that `teamix-evo init` may\n * touch. Pure read-only — never mutates the filesystem. Returns one\n * `ConflictItem` per category in stable order so callers can render a\n * deterministic wizard.\n */\nexport async function detectConflicts(cwd: string): Promise<ConflictReport> {\n const absCwd = path.resolve(cwd);\n const items: ConflictItem[] = await Promise.all([\n detectAgentsMd(absCwd),\n detectComponentsJson(absCwd),\n detectTailwindConfig(absCwd),\n detectTokens(absCwd),\n detectIndexCss(absCwd),\n detectShadcnSource(absCwd),\n detectEslintConfig(absCwd),\n detectStylelintConfig(absCwd),\n ]);\n return {\n cwd: absCwd,\n items,\n hasAnyConflict: items.some((i) => i.exists),\n };\n}\n\nasync function detectEslintConfig(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of ESLINT_CONFIG_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'eslint-config',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'merge' : 'overwrite',\n availableStrategies: ['merge', 'backup-overwrite', 'overwrite', 'skip'],\n };\n}\n\nasync function detectStylelintConfig(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of STYLELINT_CONFIG_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'stylelint-config',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'merge' : 'overwrite',\n availableStrategies: ['merge', 'backup-overwrite', 'overwrite', 'skip'],\n };\n}\n","/**\n * Legacy tokens migration — append legacy token CSS files into the new\n * standard location `tokens/tokens.overrides.css`, then back up and remove\n * the legacy files.\n *\n * Triggered when the user picks the `migrate` strategy in\n * [`init-conflicts`](./init-conflicts.ts) for the `tokens` conflict key.\n *\n * Design (per ADR 0020 + W1.4 of the manage-entry plan):\n *\n * 1. New layout owns the regenerable theme: `tokens/tokens.theme.css` is\n * written by [`runTokensInit`](./tokens-init.ts) and re-derived on every\n * install. We never migrate into the theme file.\n * 2. User-authored content from legacy single-file layouts (e.g.\n * `src/design-tokens.css`, `src/styles/design-tokens.css`,\n * `src/styles/tokens.css`) is appended to `tokens/tokens.overrides.css`\n * (frozen, user-owned) — preserving any custom CSS variables, layer\n * rules, or selectors that lived alongside the old token file.\n * 3. Every migrated source is backed up to\n * `.teamix-evo/.backups/<rel>.<iso-ts>.bak` so `restore` / manual rollback\n * can recover the pre-migration state without depending on git.\n * 4. After backup, the legacy file is removed so consumers don't keep\n * importing the stale path.\n * 5. `dryRun: true` produces the same `MigrateLegacyTokensResult` shape but\n * does not touch the filesystem — used by wizard preview & `init --dry-run`.\n *\n * The orchestrator (`project-init.ts`) calls this **after** `runTokensInit`\n * succeeds (so `tokens/tokens.overrides.css` is guaranteed to exist) and\n * **only** when the wizard returned `tokens` decision = `'migrate'` plus\n * a non-empty `legacyTokensPaths` list (the orchestrator filters out paths\n * inside `tokens/` itself before passing in).\n */\nimport * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { ensureDir, fileExists, readFileOrNull } from '../utils/fs.js';\nimport { logger } from '../utils/logger.js';\n\n/** Consumer-side directory where token files land (mirrors tokens-init.ts). */\nconst CONSUMER_TOKENS_DIR = 'tokens';\n\n/** Consumer-side filename for the frozen user-owned override. */\nconst CONSUMER_OVERRIDES_FILE = 'tokens.overrides.css';\n\n/** Default empty content for a fresh `tokens.overrides.css`. */\nconst EMPTY_OVERRIDES_TEMPLATE = `/* User-owned token overrides — frozen on subsequent installs. */\n/* See @teamix-evo/tokens variant theme.css for available CSS custom properties. */\n`;\n\nexport interface MigrateLegacyTokensOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /**\n * Legacy token CSS file paths relative to `projectRoot`.\n * Caller is responsible for filtering out paths inside `tokens/` itself.\n */\n legacyPaths: string[];\n /** When true, returns the plan without touching the filesystem. */\n dryRun?: boolean;\n}\n\nexport interface MigratedLegacyToken {\n /** Source legacy path (relative to projectRoot). */\n from: string;\n /**\n * Backup destination (relative to projectRoot).\n * `null` when `dryRun: true` — the actual path is computed at write time\n * from a fresh timestamp.\n */\n backupTo: string | null;\n /** Bytes appended to `tokens/tokens.overrides.css` (UTF-8). */\n bytesAppended: number;\n}\n\nexport interface SkippedLegacyToken {\n /** Source legacy path (relative to projectRoot). */\n from: string;\n reason: 'not-found' | 'empty';\n}\n\nexport interface MigrateLegacyTokensResult {\n /** Files whose content was appended to overrides. */\n migrated: MigratedLegacyToken[];\n /** Files that were detected but had no useful content. */\n skipped: SkippedLegacyToken[];\n /** Path to the overrides file (relative to projectRoot). */\n overridesPath: string;\n /**\n * `true` when the overrides file did not exist before this migration and\n * was created with the empty template. `false` when we appended to an\n * existing file.\n */\n overridesCreated: boolean;\n /** When `true`, no filesystem writes were performed. */\n dryRun: boolean;\n}\n\n/**\n * Format the banner that separates each migrated block inside the overrides\n * file. Kept as a free function so tests can compare exact output.\n */\nfunction buildMigrationBanner(legacyRel: string, isoTimestamp: string): string {\n return `/* === Migrated from ${legacyRel} on ${isoTimestamp} === */\\n`;\n}\n\n/**\n * Compute the backup destination (relative to `projectRoot`) for a legacy\n * file, using the same convention as [`backupFile`](../utils/fs.ts).\n */\nfunction computeBackupRel(legacyRel: string, isoTimestamp: string): string {\n const tsSafe = isoTimestamp.replace(/[:.]/g, '-');\n return path.posix.join(\n '.teamix-evo',\n '.backups',\n `${legacyRel}.${tsSafe}.bak`,\n );\n}\n\n/**\n * Perform the migration. See module-level docstring for the full contract.\n */\nexport async function migrateLegacyTokens(\n options: MigrateLegacyTokensOptions,\n): Promise<MigrateLegacyTokensResult> {\n const { projectRoot, legacyPaths, dryRun = false } = options;\n\n // De-duplicate while preserving order; normalize to forward slashes so\n // the result is stable across platforms (the rel paths come from\n // init-conflicts which already uses forward slashes).\n const seen = new Set<string>();\n const uniqueLegacy: string[] = [];\n for (const raw of legacyPaths) {\n const norm = raw.split(path.sep).join('/');\n if (!seen.has(norm)) {\n seen.add(norm);\n uniqueLegacy.push(norm);\n }\n }\n\n const overridesRel = path.posix.join(\n CONSUMER_TOKENS_DIR,\n CONSUMER_OVERRIDES_FILE,\n );\n const overridesAbs = path.join(projectRoot, overridesRel);\n\n // Read existing overrides (or seed with empty template).\n const existingOverrides = await readFileOrNull(overridesAbs);\n const overridesCreated = existingOverrides === null;\n const baseContent =\n existingOverrides === null ? EMPTY_OVERRIDES_TEMPLATE : existingOverrides;\n\n const migrated: MigratedLegacyToken[] = [];\n const skipped: SkippedLegacyToken[] = [];\n\n // Build the appended payload while collecting per-file outcomes.\n const isoTimestamp = new Date().toISOString();\n let appendedPayload = '';\n\n for (const legacyRel of uniqueLegacy) {\n const legacyAbs = path.join(projectRoot, legacyRel);\n const content = await readFileOrNull(legacyAbs);\n if (content === null) {\n skipped.push({ from: legacyRel, reason: 'not-found' });\n continue;\n }\n if (content.trim() === '') {\n skipped.push({ from: legacyRel, reason: 'empty' });\n continue;\n }\n\n const banner = buildMigrationBanner(legacyRel, isoTimestamp);\n // Ensure separation from prior content with a blank line.\n const separator =\n appendedPayload === '' && baseContent.endsWith('\\n\\n') ? '' : '\\n';\n const block = `${separator}${banner}${content}${\n content.endsWith('\\n') ? '' : '\\n'\n }`;\n appendedPayload += block;\n\n const backupRel = dryRun ? null : computeBackupRel(legacyRel, isoTimestamp);\n migrated.push({\n from: legacyRel,\n backupTo: backupRel,\n bytesAppended: Buffer.byteLength(block, 'utf-8'),\n });\n }\n\n if (dryRun || migrated.length === 0) {\n // Even with no migrated files, still report whether overrides would be\n // created so callers can show an accurate plan; in non-dry-run with no\n // migrated content we don't materialize an empty overrides here — that\n // job belongs to runTokensInit (which always seeds it).\n return {\n migrated,\n skipped,\n overridesPath: overridesRel,\n overridesCreated: dryRun ? overridesCreated : false,\n dryRun,\n };\n }\n\n // Write merged overrides (atomic via temp + rename).\n await ensureDir(path.dirname(overridesAbs));\n const merged = baseContent + appendedPayload;\n const tmp = overridesAbs + '.tmp';\n await fs.writeFile(tmp, merged, 'utf-8');\n await fs.rename(tmp, overridesAbs);\n\n // Backup + remove each successfully migrated legacy file.\n for (const entry of migrated) {\n const legacyAbs = path.join(projectRoot, entry.from);\n const backupAbs = path.join(projectRoot, entry.backupTo!);\n await ensureDir(path.dirname(backupAbs));\n // Re-read source content for the backup write (could differ if the file\n // was concurrently mutated, though that's not a supported case).\n const srcContent = await readFileOrNull(legacyAbs);\n if (srcContent === null) {\n // Vanished between read and backup — skip removal silently.\n logger.debug(\n `legacy-tokens-migrate: source disappeared before backup: ${entry.from}`,\n );\n continue;\n }\n await fs.writeFile(backupAbs, srcContent, 'utf-8');\n if (await fileExists(legacyAbs)) {\n await fs.unlink(legacyAbs);\n }\n logger.debug(\n `legacy-tokens-migrate: ${entry.from} → ${overridesRel} (backup: ${entry.backupTo})`,\n );\n }\n\n return {\n migrated,\n skipped,\n overridesPath: overridesRel,\n overridesCreated,\n dryRun: false,\n };\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { logger } from '../utils/logger.js';\n\n/**\n * `.teamix-evo/` snapshot module — captures the project state directory before\n * any mutating command runs (`init` / `update` / `variant switch`) so that\n * `teamix-evo restore <ts>` can roll back failed migrations\n * ([ADR 0019](../../../../docs/adr/0019-project-upgrade-flow.md) §2).\n *\n * **Storage layout**\n * ```\n * .teamix-evo/\n * └── .snapshots/\n * ├── 2026-06-11T20-59-03-000Z/\n * │ ├── _meta.json # { ts, reason }\n * │ ├── config.json\n * │ ├── manifest.json\n * │ └── … # everything except .snapshots/ and logs/\n * └── …\n * ```\n *\n * **Exclusions**: `.snapshots/` itself (avoid recursive snapshotting) and\n * `logs/` (high-churn telemetry; not part of the recoverable state surface).\n */\n\nconst TEAMIX_DIR = '.teamix-evo';\nconst SNAPSHOTS_DIR = '.snapshots';\nconst LOGS_DIR = 'logs';\nconst META_FILE = '_meta.json';\n/** Default snapshot retention — older snapshots beyond this count are pruned. */\nconst DEFAULT_KEEP = 5;\n\n/** Reason why a snapshot was taken — surfaces in `restore` listing. */\nexport type SnapshotReason =\n | 'init'\n | 'update'\n | 'switch'\n | 'restore'\n | 'manual';\n\n/** Result of `createSnapshot` when a snapshot was actually taken. */\nexport interface SnapshotResult {\n /** Filesystem-safe UTC timestamp identifier (e.g. `2026-06-11T20-59-03-000Z`). */\n ts: string;\n /** Absolute path to the snapshot directory. */\n path: string;\n}\n\nexport interface CreateSnapshotOptions {\n /** Why the snapshot is being taken — recorded in `_meta.json`. */\n reason?: SnapshotReason;\n /** Retention count (default 5). Older snapshots beyond this are pruned. */\n keep?: number;\n /**\n * Snapshot ts that MUST NOT be pruned even if it falls outside the `keep`\n * window. Used by {@link restoreSnapshot} to prevent the snapshot it is\n * about to read from being pruned by the pre-restore safety snapshot's\n * own retention pass — see ADR 0019 §2.\n */\n protectedTs?: string;\n}\n\n/** A listed snapshot entry returned by `listSnapshots`. */\nexport interface SnapshotEntry {\n /** Filesystem-safe ts identifier (the snapshot directory name). */\n ts: string;\n /** Original ISO ts as recorded in `_meta.json` (or null if meta missing). */\n isoTs: string | null;\n /** Reason recorded in `_meta.json` (or null if meta missing). */\n reason: SnapshotReason | null;\n /** Absolute path to the snapshot directory. */\n path: string;\n}\n\n/**\n * Convert an ISO-8601 timestamp into a filesystem-safe directory name by\n * replacing `:` and `.` with `-`. Order-preserving (lexicographic sort still\n * matches chronological order).\n */\nfunction isoToFsSafe(iso: string): string {\n return iso.replace(/[:.]/g, '-');\n}\n\n/**\n * Inverse of {@link isoToFsSafe} — best-effort reconstruction of the original\n * ISO string. Used when `_meta.json` is missing so `listSnapshots` can still\n * surface a reasonable timestamp.\n */\nfunction fsSafeToIso(safe: string): string {\n // 2026-06-11T20-59-03-000Z → 2026-06-11T20:59:03.000Z\n return safe.replace(\n /^(\\d{4}-\\d{2}-\\d{2})T(\\d{2})-(\\d{2})-(\\d{2})-(\\d{3})(Z)$/,\n '$1T$2:$3:$4.$5$6',\n );\n}\n\n/**\n * Capture a point-in-time copy of `.teamix-evo/` (excluding `.snapshots/`\n * and `logs/`). Returns `null` when there is nothing to snapshot\n * (`.teamix-evo/` does not yet exist — typical on the very first `init` run).\n *\n * Subsequent calls automatically prune old snapshots beyond `opts.keep`\n * (default 5) so the directory does not grow unbounded.\n */\nexport async function createSnapshot(\n projectRoot: string,\n opts: CreateSnapshotOptions = {},\n): Promise<SnapshotResult | null> {\n const teamixDir = path.join(projectRoot, TEAMIX_DIR);\n try {\n const stat = await fs.stat(teamixDir);\n if (!stat.isDirectory()) return null;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return null;\n throw err;\n }\n\n const isoTs = new Date().toISOString();\n const ts = isoToFsSafe(isoTs);\n const snapshotRoot = path.join(teamixDir, SNAPSHOTS_DIR);\n const target = path.join(snapshotRoot, ts);\n await fs.mkdir(target, { recursive: true });\n\n const entries = await fs.readdir(teamixDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name === SNAPSHOTS_DIR) continue;\n if (entry.name === LOGS_DIR) continue;\n const src = path.join(teamixDir, entry.name);\n const dst = path.join(target, entry.name);\n await fs.cp(src, dst, { recursive: true });\n }\n\n const meta = {\n ts: isoTs,\n reason: opts.reason ?? 'manual',\n };\n await fs.writeFile(\n path.join(target, META_FILE),\n JSON.stringify(meta, null, 2) + '\\n',\n 'utf-8',\n );\n\n logger.debug(\n `Snapshot created → ${path.relative(projectRoot, target)} (${meta.reason})`,\n );\n\n const keep = opts.keep ?? DEFAULT_KEEP;\n await pruneSnapshots(projectRoot, keep, { protectedTs: opts.protectedTs });\n\n return { ts, path: target };\n}\n\n/**\n * List existing snapshots ordered newest-first. Returns an empty array when\n * `.teamix-evo/.snapshots/` does not exist.\n */\nexport async function listSnapshots(\n projectRoot: string,\n): Promise<SnapshotEntry[]> {\n const snapshotRoot = path.join(projectRoot, TEAMIX_DIR, SNAPSHOTS_DIR);\n let entries: import('node:fs').Dirent[];\n try {\n entries = await fs.readdir(snapshotRoot, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') return [];\n throw err;\n }\n\n const result: SnapshotEntry[] = [];\n for (const entry of entries) {\n if (!entry.isDirectory()) continue;\n const dir = path.join(snapshotRoot, entry.name);\n let isoTs: string | null = null;\n let reason: SnapshotReason | null = null;\n try {\n const raw = await fs.readFile(path.join(dir, META_FILE), 'utf-8');\n const parsed = JSON.parse(raw) as {\n ts?: unknown;\n reason?: unknown;\n };\n if (typeof parsed.ts === 'string') isoTs = parsed.ts;\n if (\n typeof parsed.reason === 'string' &&\n ['init', 'update', 'switch', 'restore', 'manual'].includes(\n parsed.reason,\n )\n ) {\n reason = parsed.reason as SnapshotReason;\n }\n } catch {\n // _meta.json missing or unparseable → reconstruct ts from directory name\n isoTs = fsSafeToIso(entry.name);\n }\n result.push({ ts: entry.name, isoTs, reason, path: dir });\n }\n\n // Directory names embed UTC ISO timestamps; lexicographic sort = chronological.\n result.sort((a, b) => (a.ts < b.ts ? 1 : a.ts > b.ts ? -1 : 0));\n return result;\n}\n\nexport interface PruneSnapshotsOptions {\n /**\n * Snapshot ts that MUST NOT be pruned even if it falls outside the `keep`\n * window. Lets callers (notably `restoreSnapshot`) protect a snapshot they\n * are about to read from concurrent retention.\n */\n protectedTs?: string;\n}\n\n/**\n * Delete snapshots older than the most recent `keep` entries. Returns the\n * list of pruned ts identifiers (oldest first).\n *\n * When `opts.protectedTs` is set, that snapshot is preserved regardless of\n * its position — used to defuse the restore-prune race (ADR 0019 §2).\n */\nexport async function pruneSnapshots(\n projectRoot: string,\n keep: number = DEFAULT_KEEP,\n opts: PruneSnapshotsOptions = {},\n): Promise<string[]> {\n if (keep < 0)\n throw new Error(`pruneSnapshots: keep must be >= 0, got ${keep}`);\n const snapshots = await listSnapshots(projectRoot);\n if (snapshots.length <= keep) return [];\n\n const tail = snapshots.slice(keep); // newest-first → tail is oldest\n const toRemove = opts.protectedTs\n ? tail.filter((s) => s.ts !== opts.protectedTs)\n : tail;\n const removed: string[] = [];\n for (const snap of toRemove) {\n await fs.rm(snap.path, { recursive: true, force: true });\n removed.push(snap.ts);\n logger.debug(`Pruned snapshot ${snap.ts}`);\n }\n // Return oldest-first for ergonomic caller logging.\n return removed.reverse();\n}\n\n/**\n * Restore `.teamix-evo/` from a previously captured snapshot.\n *\n * Behaviour:\n * 1. Verify the requested snapshot exists (throws otherwise).\n * 2. Take a \"pre-restore\" snapshot of the current state so the restore itself\n * is reversible (recorded with `reason: 'restore'`).\n * 3. Delete every entry under `.teamix-evo/` *except* `.snapshots/` and\n * `logs/`.\n * 4. Copy the snapshot's contents (excluding its `_meta.json`) back into\n * `.teamix-evo/`.\n *\n * Throws when the snapshot ts cannot be located so callers can surface a\n * clear message (\"snapshot not found, run `teamix-evo restore --list` to see\n * available timestamps\").\n */\nexport async function restoreSnapshot(\n projectRoot: string,\n ts: string,\n): Promise<void> {\n const snapshotRoot = path.join(projectRoot, TEAMIX_DIR, SNAPSHOTS_DIR);\n const target = path.join(snapshotRoot, ts);\n try {\n const stat = await fs.stat(target);\n if (!stat.isDirectory()) {\n throw new Error(`Snapshot path is not a directory: ${target}`);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n throw new Error(\n `Snapshot not found: \"${ts}\". Run \\`teamix-evo restore --list\\` to see available timestamps.`,\n );\n }\n throw err;\n }\n\n // 1. Pre-restore safety snapshot. Pass `protectedTs: ts` so the snapshot we\n // are about to read from is NOT pruned out of the retention window if it\n // happens to fall beyond `keep` (ADR 0019 §2 — restore-prune race).\n await createSnapshot(projectRoot, { reason: 'restore', protectedTs: ts });\n\n // 2. Wipe `.teamix-evo/` (except .snapshots/ and logs/) so leftover files\n // from a half-applied update don't bleed into the restored state.\n const teamixDir = path.join(projectRoot, TEAMIX_DIR);\n const live = await fs.readdir(teamixDir, { withFileTypes: true });\n for (const entry of live) {\n if (entry.name === SNAPSHOTS_DIR) continue;\n if (entry.name === LOGS_DIR) continue;\n await fs.rm(path.join(teamixDir, entry.name), {\n recursive: true,\n force: true,\n });\n }\n\n // 3. Copy snapshot contents back (skip _meta.json — it's snapshot metadata,\n // not part of the recoverable state).\n const snapshotEntries = await fs.readdir(target, { withFileTypes: true });\n for (const entry of snapshotEntries) {\n if (entry.name === META_FILE) continue;\n const src = path.join(target, entry.name);\n const dst = path.join(teamixDir, entry.name);\n await fs.cp(src, dst, { recursive: true });\n }\n\n logger.debug(`Restored .teamix-evo/ from snapshot ${ts}`);\n}\n","/**\n * File-change ledger for the init / update pipelines.\n *\n * Phase 1.A1 (init 落地改进): every orchestrator step records what it touched\n * so the CLI can print a single \"新建 / 修改 / 备份 / 删除\" summary at the end.\n * Today's pipeline only piggybacks on side-effectful sub-commands' result\n * objects (`resources`, `wroteEslint`, …) — without an explicit ledger the\n * user has no way to see, in one glance, which user-owned files moved.\n *\n * Design constraints:\n * - Pure data type — no I/O, no global mutable state. The orchestrator passes\n * a single mutable array down to each helper; sub-step adapters return\n * `FileChange[]` they can derive from their own return values.\n * - \"modified\" vs \"created\" is decided by checking whether a fresh backup\n * exists under `.teamix-evo/.backups/<rel>.*.bak` for that path — see\n * {@link diffBackupSet}. Any path that gained a backup during the pipeline\n * is classified `modified`; everything else surfaced by the steps is\n * `created`. This keeps the classification truthful even when a sub-step\n * has no idea whether the file pre-existed.\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport type FileChangeKind = 'created' | 'modified' | 'backed-up' | 'deleted';\n\nexport interface FileChange {\n kind: FileChangeKind;\n /** Project-root-relative path, posix style (forward slashes). */\n path: string;\n /** Originating pipeline step (free-form to avoid coupling on `ProjectInitStepName`). */\n step: string;\n /** Optional human-readable note (e.g. `frozen` / `regenerable` / `managed`). */\n detail?: string;\n}\n\n/**\n * Convert any abs/rel path to a project-root-relative posix path.\n * Returns the input unchanged if it cannot be relativised.\n */\nexport function toRelativePosix(p: string, projectRoot: string): string {\n let rel = p;\n if (path.isAbsolute(p)) {\n rel = path.relative(projectRoot, p);\n }\n return rel.split(path.sep).join('/');\n}\n\n/**\n * Recursively enumerate `.teamix-evo/.backups/` and return the set of\n * original (project-root-relative) paths that have at least one `.bak` copy.\n *\n * Backup file names follow `<rel>.<isoTsSafe>.bak` where `<isoTsSafe>` is the\n * output of `new Date().toISOString().replace(/[:.]/g, '-')` — a fixed-shape\n * `YYYY-MM-DDTHH-MM-SS-mmmZ` token. We strip that suffix to recover `<rel>`.\n *\n * Returns an empty set when the backups directory does not exist.\n */\nexport async function listBackupOriginals(\n projectRoot: string,\n): Promise<Set<string>> {\n const backupsDir = path.join(projectRoot, '.teamix-evo', '.backups');\n const out = new Set<string>();\n const stack: string[] = [backupsDir];\n while (stack.length > 0) {\n const dir = stack.pop()!;\n let entries: import('node:fs').Dirent[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw err;\n }\n for (const e of entries) {\n const full = path.join(dir, e.name);\n if (e.isDirectory()) {\n stack.push(full);\n } else if (e.isFile() && e.name.endsWith('.bak')) {\n const rel = path.relative(backupsDir, full);\n const original = stripBackupSuffix(rel);\n if (original) out.add(original.split(path.sep).join('/'));\n }\n }\n }\n return out;\n}\n\n/**\n * Strip the `.<isoTsSafe>.bak` tail from a backup-relative path. Returns null\n * when the suffix doesn't match (file isn't one of ours — leave untouched).\n */\nexport function stripBackupSuffix(rel: string): string | null {\n const m = rel.match(\n /^(.+)\\.\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}Z\\.bak$/,\n );\n return m?.[1] ?? null;\n}\n\n/**\n * Compute the relative-path set that gained a fresh backup between `before`\n * and `after` (i.e. paths the pipeline modified in-place).\n */\nexport function diffBackupSet(\n before: ReadonlySet<string>,\n after: ReadonlySet<string>,\n): Set<string> {\n const out = new Set<string>();\n for (const p of after) {\n if (!before.has(p)) out.add(p);\n }\n return out;\n}\n\n/**\n * Format a flat list of `FileChange` rows into a markdown-ish summary.\n * Returns an array of lines suitable for the CLI logger.\n *\n * Empty buckets are omitted from the output. Order: created → modified →\n * backed-up → deleted. Each bucket lists paths sorted lexicographically with\n * de-duplication on `(kind, path)`.\n */\nexport function formatFileChangeSummary(changes: FileChange[]): string[] {\n if (changes.length === 0) return [];\n const buckets: Record<FileChangeKind, Map<string, FileChange>> = {\n created: new Map(),\n modified: new Map(),\n 'backed-up': new Map(),\n deleted: new Map(),\n };\n for (const c of changes) {\n const existing = buckets[c.kind].get(c.path);\n if (!existing) buckets[c.kind].set(c.path, c);\n }\n const order: Array<[FileChangeKind, string]> = [\n ['created', '🆕 新建'],\n ['modified', '✏️ 修改'],\n ['backed-up', '💾 已备份'],\n ['deleted', '🗑 删除'],\n ];\n const lines: string[] = [];\n for (const [kind, label] of order) {\n const bucket = buckets[kind];\n if (bucket.size === 0) continue;\n lines.push(`${label}(${bucket.size}):`);\n const sorted = [...bucket.values()].sort((a, b) =>\n a.path.localeCompare(b.path),\n );\n for (const c of sorted) {\n const detail = c.detail ? ` — ${c.detail}` : '';\n lines.push(` • ${c.path} [${c.step}]${detail}`);\n }\n }\n return lines;\n}\n","/**\n * Programmatic orchestrator for `teamix-evo init` (existing-project adoption).\n *\n * Consumes {@link InitWizardAnswers} produced by `runInitWizard` and drives\n * the existing core sub-commands (`runTokensInit`, `runSkillsAdd`,\n * `runGenerateAgentsMd`, `runUiInit`, `runUiAdd`, `runLintInit`) in a fixed\n * order. Sub-commands are invoked silently — no interactive prompts here.\n *\n * Conflict handling:\n * - `conflictDecisions[key] === 'skip'` skips the corresponding step entirely.\n * - `'overwrite'` is the trivial path (the underlying core APIs already write).\n * - `'merge-managed'` (agents-md) is implemented today via\n * `runGenerateAgentsMd` which writes managed regions natively.\n * - `'skip-existing'` (shadcn-source) maps to `runUiAdd({ overwrite: false })`,\n * the existing default.\n * - All other strategies (`diff-prompt`, `backup-overwrite`, `migrate`,\n * `coexist`, `append`, `per-file-prompt`) require the managed-region engine\n * from batch 4 — they are recorded to `pendingConflictWork` so the CLI\n * surface can guide the user to the followup `teamix-evo conflict resolve`\n * step (post-batch-4).\n *\n * No interactive prompts, no `process.exit`. Throws on hard failure (P8).\n */\nimport type { InitWizardAnswers } from '../commands/init/wizard.js';\nimport type { ConflictKey, ConflictStrategy } from './init-conflicts.js';\nimport type { SkillIde } from '@teamix-evo/registry';\nimport { runTokensInit } from './tokens-init.js';\nimport { migrateLegacyTokens } from './legacy-tokens-migrate.js';\nimport { runSkillsAdd } from './skills-add.js';\nimport { runGenerateAgentsMd } from './agents-md.js';\nimport { runUiInit } from './ui-init.js';\nimport { runUiAdd } from './ui-add.js';\nimport { runLintInit } from './lint-init.js';\nimport { loadUiData } from './ui-client.js';\nimport { createSnapshot, type SnapshotResult } from './snapshot.js';\nimport { getErrorMessage } from '../utils/error.js';\nimport {\n type FileChange,\n diffBackupSet,\n listBackupOriginals,\n toRelativePosix,\n} from './file-changes.js';\n\n/**\n * Baseline UI component subset for `uiSelection === 'baseline'`. Mirrors the\n * opentrek / uni-manager preset baseline (kept in sync intentionally so the\n * existing-project init produces the same starter shape as `npm create\n * teamix-evo`). Variants pull additional pieces via `bizUi` later.\n */\nconst BASELINE_UI_ENTRIES = [\n 'button',\n 'button-group',\n 'input',\n 'form',\n 'card',\n 'collapsible',\n 'dialog',\n 'dropdown-menu',\n 'tabs',\n 'table',\n 'sidebar',\n 'page-shell',\n 'page-header',\n] as const;\n\nexport type ProjectInitStepName =\n | 'tokens'\n | 'skills'\n | 'agents-md'\n | 'ui-init'\n | 'ui-add'\n | 'lint';\n\nexport type ProjectInitStepStatus = 'ok' | 'skip' | 'fail' | 'planned';\n\nexport interface ProjectInitStep {\n name: ProjectInitStepName;\n status: ProjectInitStepStatus;\n detail?: string;\n /**\n * Files this step touched (Phase 1.A1). Empty when the step skipped or\n * failed before any I/O. The `kind` is `created` by default; the orchestrator\n * upgrades entries to `modified` post-hoc by checking the backup ledger\n * (`.teamix-evo/.backups/`).\n */\n changes?: FileChange[];\n}\n\nexport interface PendingConflictWork {\n key: ConflictKey;\n strategy: ConflictStrategy;\n reason: string;\n}\n\nexport interface ResumeHint {\n /** The first step that failed (caller resumes from here). */\n failedAt: ProjectInitStepName;\n /** Steps already finished (status === 'ok'); will short-circuit on resume. */\n completed: ProjectInitStepName[];\n /** All steps that ended in fail status. */\n failed: ProjectInitStepName[];\n /** Human-readable error from the first failed step. */\n error: string;\n /**\n * Suggested CLI command to resume. Today this is just `teamix-evo init`\n * itself — every sub-step is idempotent (returns `already-initialized`\n * when the matching state file already exists), so a re-run continues\n * from the failure point automatically. Future batches may grow a\n * dedicated `--resume` flag with a richer recovery model (batch 3).\n */\n resumeCommand: string;\n}\n\nexport interface RunProjectInitOptions {\n /** Absolute project root (existing repo to adopt teamix-evo into). */\n projectRoot: string;\n /** Wizard outcome (single source of truth for every silent sub-command). */\n answers: InitWizardAnswers;\n /**\n * Override the resolved UI entry list. When provided, replaces the\n * `answers.uiSelection`-driven list (`'baseline'` / `'all'`). Useful for\n * tests and for callers that want to install a custom subset.\n */\n uiEntries?: string[];\n /**\n * If true, skip `npm install` for lint deps. Defaults to `false` so lint\n * works out of the box; pass `true` from the create scaffold which installs\n * everything in one batch.\n */\n skipInstall?: boolean;\n /**\n * Legacy token CSS files (paths relative to `projectRoot`) detected by\n * `detectConflicts` for the `tokens` key. When `conflictDecisions.tokens`\n * is `'migrate'` and this list is non-empty, the orchestrator appends\n * each file's content into `tokens/tokens.overrides.css` and backs the\n * legacy files up to `.teamix-evo/.backups/` (W1.4 of the manage-entry\n * plan; see [`legacy-tokens-migrate`](./legacy-tokens-migrate.ts)).\n *\n * Ignored for any other `tokens` decision. The caller (init command) is\n * responsible for filtering out paths already inside `tokens/`.\n */\n legacyTokensPaths?: string[];\n /**\n * Phase 3.E: existing ESLint config paths (relative to `projectRoot`)\n * detected by `detectConflicts` for the `eslint-config` key. Used to\n * back up the consumer's file before writing the teamix-evo template,\n * and to gate the `merge` / `backup-overwrite` / `skip` strategies in\n * `runLintInit`.\n */\n legacyEslintPaths?: string[];\n /**\n * Phase 3.E: existing Stylelint config paths (relative to `projectRoot`).\n */\n legacyStylelintPaths?: string[];\n /** Step-level progress hook (caller controls presentation). */\n onStep?: (step: ProjectInitStep) => void;\n /**\n * If true, plan-only mode: compute the full step list without running any\n * sub-command. Returns each step with `status: 'planned'`.\n */\n dryRun?: boolean;\n}\n\nexport interface RunProjectInitResult {\n status: 'installed' | 'partial' | 'dry-run';\n steps: ProjectInitStep[];\n /** Conflicts whose strategy needs the post-batch-4 managed-region engine. */\n pendingConflictWork: PendingConflictWork[];\n /**\n * Aggregated, classified file-change ledger covering every step\n * (Phase 1.A1). Backup entries are surfaced as `kind: 'backed-up'` so the\n * CLI can render a four-bucket summary (新建 / 修改 / 备份 / 删除).\n */\n changes: FileChange[];\n /**\n * Present when at least one step ended in `fail`. Lets the CLI surface a\n * structured recovery message instead of just a stack-trace, and gives\n * programmatic consumers a deterministic field to branch on.\n */\n resumeHint?: ResumeHint;\n /**\n * Pre-init snapshot of `.teamix-evo/`, captured automatically before any\n * file is written ([ADR 0019](../../../../docs/adr/0019-project-upgrade-flow.md) §2).\n *\n * - `null` on first-ever init (`.teamix-evo/` did not yet exist) and on\n * `dryRun`.\n * - Failure to capture a snapshot is **non-fatal** — surfaced via\n * {@link snapshotError} so the CLI can warn the user. The init pipeline\n * itself still runs.\n */\n snapshot?: SnapshotResult | null;\n /** Reason a snapshot capture failed (best-effort — never blocks init). */\n snapshotError?: string;\n}\n\n/**\n * Steps whose failure must abort the pipeline (downstream steps depend on\n * the state they write). Non-critical steps record `fail` and continue, so\n * the user gets as much done as possible in one pass.\n *\n * - `tokens` writes `.teamix-evo/tokens-lock.json` + `config.json` (skills /\n * ui depend on the variant + config existing).\n * - `skills` records the project's IDE registration; agents-md reads back\n * the manifest.\n * - `ui-init` writes `packages.ui` config (ui-add asserts on it).\n *\n * `agents-md`, `ui-add`, `lint` are independent leaves: any can fail without\n * blocking the others.\n */\nconst CRITICAL_STEPS: ReadonlySet<ProjectInitStepName> = new Set([\n 'tokens',\n 'skills',\n 'ui-init',\n]);\n\n/**\n * Strategies that are fully implementable in the current orchestrator (no\n * managed-region engine required). Anything outside this set is recorded as\n * `pendingConflictWork`.\n */\nconst IMPLEMENTED_STRATEGIES: Record<ConflictKey, ConflictStrategy[]> = {\n // 'agents-md': both 'merge-managed' (Phase 2.B — splice the\n // teamix-evo-skills managed region) and 'overwrite' (full rewrite) write\n // through `runGenerateAgentsMd`.\n 'agents-md': ['merge-managed', 'overwrite', 'skip'],\n tokens: ['migrate', 'overwrite', 'skip'],\n 'components-json': ['overwrite', 'skip'],\n 'shadcn-source': ['overwrite', 'skip-existing', 'skip'],\n 'tailwind-config': ['skip'],\n 'index-css': ['skip'],\n // Phase 3.E: lint conflict strategies are honored end-to-end by\n // `runLintInit` (backup user file + write template, optional AI-assist hint).\n 'eslint-config': ['merge', 'backup-overwrite', 'skip', 'overwrite'],\n 'stylelint-config': ['merge', 'backup-overwrite', 'skip', 'overwrite'],\n};\n\nfunction pickIde(ides: readonly SkillIde[]): string {\n return ides[0] ?? 'qoder';\n}\n\nfunction strategyImplemented(\n key: ConflictKey,\n strategy: ConflictStrategy,\n): boolean {\n return IMPLEMENTED_STRATEGIES[key]?.includes(strategy) ?? false;\n}\n\nasync function resolveUiEntries(\n options: RunProjectInitOptions,\n): Promise<string[]> {\n if (options.uiEntries && options.uiEntries.length > 0) {\n return [...options.uiEntries];\n }\n if (options.answers.uiSelection === 'all') {\n const { manifest } = await loadUiData('@teamix-evo/ui');\n return manifest.entries.map((e) => e.id);\n }\n return [...BASELINE_UI_ENTRIES];\n}\n\n// ─── Per-step `FileChange` adapters (Phase 1.A1) ──────────────────────────────────\n// Each adapter consumes a sub-command result and produces the user-facing\n// `created` rows for the ledger. The orchestrator post-processes these into\n// `modified` rows by diffing `.teamix-evo/.backups/`.\n\ntype TokensInitResult = Awaited<ReturnType<typeof runTokensInit>>;\ntype SkillsAddResult = Awaited<ReturnType<typeof runSkillsAdd>>;\ntype UiAddResult = Awaited<ReturnType<typeof runUiAdd>>;\ntype LintInitResult = Awaited<ReturnType<typeof runLintInit>>;\n\nfunction deriveTokensChanges(\n result: TokensInitResult,\n projectRoot: string,\n): FileChange[] {\n if (result.status !== 'installed') return [];\n return result.resources.map((r) => ({\n kind: 'created' as const,\n path: toRelativePosix(r.target, projectRoot),\n step: 'tokens',\n detail: r.strategy,\n }));\n}\n\nfunction deriveSkillsChanges(\n result: SkillsAddResult,\n projectRoot: string,\n): FileChange[] {\n if (result.status !== 'installed') return [];\n // Skills install writes (a) the source mirror under `.teamix-evo/skills/`,\n // (b) one IDE mirror per `ides` per skill. The full list can be 30+ files\n // for a 2-skill / 2-IDE config which is too noisy. Collapse to one entry\n // per added skill id, pointing at the source-of-truth SKILL.md so the user\n // knows where to read the contract.\n return result.addedSkillIds.map((id) => ({\n kind: 'created' as const,\n path: `.teamix-evo/skills/${id}/SKILL.md`,\n step: 'skills',\n detail: 'skill installed (source mirror + IDE mirrors)',\n }));\n}\n\nfunction deriveUiAddChanges(\n result: UiAddResult,\n projectRoot: string,\n): FileChange[] {\n // result.resources covers BOTH freshly written files and pre-existing\n // frozen entries that we left untouched. We only want to surface what\n // actually changed on disk — those whose hash matches the just-written\n // content (`written` count). Without per-file write/skip flags we use a\n // simple approximation: emit the latest `written` resources by trusting\n // the order — the installer iterates entries in resolved order and the\n // resource array preserves that order.\n const out: FileChange[] = [];\n let remaining = result.written;\n // Iterate from the tail so already-installed (skipped) resources at the\n // head don't eat the budget. The installer appends per file, so the last\n // `written` entries correspond to fresh writes.\n for (let i = result.resources.length - 1; i >= 0 && remaining > 0; i--) {\n const r = result.resources[i]!;\n out.unshift({\n kind: 'created',\n path: toRelativePosix(r.target, projectRoot),\n step: 'ui-add',\n detail: r.strategy,\n });\n remaining--;\n }\n return out;\n}\n\nfunction deriveLintChanges(result: LintInitResult): FileChange[] {\n if (result.status !== 'installed') return [];\n const out: FileChange[] = [];\n if (result.eslint) {\n out.push({\n kind: 'created',\n path: 'eslint.config.js',\n step: 'lint',\n detail: '@teamix-evo/eslint-config consumer preset',\n });\n }\n if (result.stylelint) {\n out.push({\n kind: 'created',\n path: 'stylelint.config.cjs',\n step: 'lint',\n detail: '@teamix-evo/stylelint-config consumer preset',\n });\n }\n // package.json only ends up in the ledger when lint / lint:css scripts\n // were actually inserted. The orchestrator will upgrade `created` to\n // `modified` if a backup ledger entry shows up.\n if (result.packageJsonPatched) {\n out.push({\n kind: 'created',\n path: 'package.json',\n step: 'lint',\n detail: 'scripts.lint / scripts[\"lint:css\"]',\n });\n }\n return out;\n}\n\n/**\n * Existing-project init pipeline.\n *\n * Order:\n * 1. tokens init (auto-installs `teamix-evo-design-${variant}` skill)\n * 2. skills add (`teamix-evo-code-${variant}`; entry skill is global, ADR 0033)\n * 3. AGENTS.md (skill trigger fallback, ADR 0038)\n * 4. ui init + ui add (gated by `withUi`)\n * 5. lint init (gated by `withLint`)\n */\nexport async function runProjectInit(\n options: RunProjectInitOptions,\n): Promise<RunProjectInitResult> {\n const { projectRoot, answers, dryRun = false, onStep } = options;\n const ide = pickIde(answers.ides);\n const steps: ProjectInitStep[] = [];\n const pending: PendingConflictWork[] = [];\n const allChanges: FileChange[] = [];\n\n // Phase 1.A1: capture the pre-init backup ledger so we can tell, per file,\n // whether the pipeline truly created it or merely rewrote it (rewrites land\n // a fresh `.bak` under .teamix-evo/.backups/ thanks to the A2 hooks).\n const backupsBefore = dryRun\n ? new Set<string>()\n : await listBackupOriginals(projectRoot).catch(() => new Set<string>());\n\n // ─── Pre-flight: snapshot `.teamix-evo/` so a partial / failed init can be\n // rolled back via `teamix-evo restore <ts>` (ADR 0019 §2). Best-effort:\n // dry-run skips, fresh installs return null (nothing to snapshot), I/O\n // errors are surfaced but never abort the pipeline.\n let snapshot: SnapshotResult | null = null;\n let snapshotError: string | undefined;\n if (!dryRun) {\n try {\n snapshot = await createSnapshot(projectRoot, { reason: 'init' });\n } catch (err) {\n snapshotError = getErrorMessage(err);\n }\n }\n /**\n * Set to `true` once a critical step (tokens / skills / ui-init) has\n * failed; subsequent critical steps short-circuit to `skip` so we never\n * cascade onto unsatisfied state. Non-critical leaves (agents-md / ui-add\n * / lint) keep running so the user gets as much done as possible per pass.\n */\n let aborted = false;\n /**\n * First failed step — powers the recovery summary in `resumeHint`.\n * Wrapped in an object so closures (`recordFailure`) can mutate the field\n * without TypeScript narrowing the binding to `never` after the closing\n * `if (firstFailure.value)` guard.\n */\n const firstFailure: {\n value: { step: ProjectInitStepName; error: string } | null;\n } = {\n value: null,\n };\n\n function record(step: ProjectInitStep): void {\n steps.push(step);\n onStep?.(step);\n if (step.changes && step.changes.length > 0) {\n allChanges.push(...step.changes);\n }\n }\n\n function recordPending(key: ConflictKey): void {\n const strategy = answers.conflictDecisions[key];\n if (!strategy) return;\n if (strategyImplemented(key, strategy)) return;\n pending.push({\n key,\n strategy,\n reason: `Strategy \"${strategy}\" requires the managed-region engine (batch 4); recorded for follow-up.`,\n });\n }\n\n /** Record a step failure; flag abort if the step is critical. */\n function recordFailure(name: ProjectInitStepName, err: unknown): void {\n const message = getErrorMessage(err);\n record({ name, status: 'fail', detail: message });\n if (!firstFailure.value)\n firstFailure.value = { step: name, error: message };\n if (CRITICAL_STEPS.has(name)) aborted = true;\n }\n\n // ─── 1. tokens ──────────────────────────────────────────────────────────\n const tokensDecision = answers.conflictDecisions.tokens;\n const legacyTokensPaths = options.legacyTokensPaths ?? [];\n const wantMigrate =\n tokensDecision === 'migrate' && legacyTokensPaths.length > 0;\n if (tokensDecision === 'skip') {\n record({\n name: 'tokens',\n status: 'skip',\n detail: 'conflict strategy = skip',\n });\n } else if (dryRun) {\n const planDetail = wantMigrate\n ? `runTokensInit(variant=${answers.variant}); migrateLegacyTokens(${\n legacyTokensPaths.length\n } file${legacyTokensPaths.length === 1 ? '' : 's'})`\n : `runTokensInit(variant=${answers.variant})`;\n record({\n name: 'tokens',\n status: 'planned',\n detail: planDetail,\n });\n } else {\n try {\n const result = await runTokensInit({\n projectRoot,\n variant: answers.variant,\n ide,\n });\n let detail =\n result.status === 'installed'\n ? `${result.packageName}@${result.version} (${result.count} files)`\n : result.status;\n if (wantMigrate) {\n // Migrate is best-effort: a failure here doesn't invalidate the\n // tokens install itself (theme + overrides are already in place),\n // it just leaves the legacy files alone for the user to handle.\n // We surface the outcome via the step's `detail` so the CLI prints\n // it without inventing a new step name.\n try {\n const m = await migrateLegacyTokens({\n projectRoot,\n legacyPaths: legacyTokensPaths,\n });\n detail += `; migrated ${m.migrated.length}/${\n legacyTokensPaths.length\n } legacy file${legacyTokensPaths.length === 1 ? '' : 's'} → ${\n m.overridesPath\n }`;\n if (m.skipped.length > 0) {\n detail += ` (skipped ${m.skipped.length})`;\n }\n } catch (err) {\n detail += `; migrate failed: ${getErrorMessage(err)}`;\n }\n }\n record({\n name: 'tokens',\n status: 'ok',\n detail,\n changes: deriveTokensChanges(result, projectRoot),\n });\n } catch (err) {\n recordFailure('tokens', err);\n }\n }\n recordPending('tokens');\n\n // ─── 2. skills (code-${variant} only — manage is global, design auto-installed by tokens) ──\n const codeSkillId = `teamix-evo-code-${answers.variant}`;\n if (dryRun) {\n record({\n name: 'skills',\n status: 'planned',\n detail: `runSkillsAdd(${codeSkillId})`,\n });\n } else if (aborted) {\n record({\n name: 'skills',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n } else {\n try {\n const result = await runSkillsAdd({\n projectRoot,\n names: [codeSkillId],\n ides: answers.ides,\n scope: answers.scope,\n ide,\n });\n record({\n name: 'skills',\n status: 'ok',\n detail:\n result.status === 'installed'\n ? `added: ${result.addedSkillIds.join(', ') || 'none'}; existing: ${\n result.skippedSkillIds.join(', ') || 'none'\n }`\n : result.status,\n changes: deriveSkillsChanges(result, projectRoot),\n });\n } catch (err) {\n recordFailure('skills', err);\n }\n }\n\n // ─── 3. AGENTS.md ──────────────────────────────────────────────────────\n const agentsMdDecision = answers.conflictDecisions['agents-md'];\n const agentsMdSkillIds = [\n `teamix-evo-design-${answers.variant}`,\n codeSkillId,\n ];\n if (agentsMdDecision === 'skip') {\n record({\n name: 'agents-md',\n status: 'skip',\n detail: 'conflict strategy = skip',\n });\n } else if (dryRun) {\n record({\n name: 'agents-md',\n status: 'planned',\n detail: `runGenerateAgentsMd(${agentsMdSkillIds.length} skills)`,\n });\n } else {\n try {\n const result = await runGenerateAgentsMd({\n projectRoot,\n variant: answers.variant,\n skillIds: agentsMdSkillIds,\n // Phase 2.B: when the user picked `merge-managed` on conflict, only\n // rewrite the `teamix-evo-skills` managed region so hand-written\n // sections survive the regenerate step. `overwrite` keeps the\n // historical full-rewrite default.\n mode:\n agentsMdDecision === 'merge-managed' ? 'merge-managed' : 'overwrite',\n });\n record({\n name: 'agents-md',\n status: 'ok',\n detail: `${result.skillCount} skill index${\n result.missingSkillIds.length > 0\n ? ` (missing SKILL.md: ${result.missingSkillIds.join(', ')})`\n : ''\n }`,\n changes: [\n {\n kind: result.backedUp ? 'modified' : 'created',\n path: toRelativePosix(result.path, projectRoot),\n step: 'agents-md',\n detail: 'skill-trigger fallback (ADR 0038)',\n },\n ],\n });\n } catch (err) {\n recordFailure('agents-md', err);\n }\n }\n recordPending('agents-md');\n\n // ─── 4. ui init + ui add ────────────────────────────────────────────────\n const componentsJsonDecision = answers.conflictDecisions['components-json'];\n const shadcnDecision = answers.conflictDecisions['shadcn-source'];\n const skipUiInit = !answers.withUi || componentsJsonDecision === 'skip';\n\n if (skipUiInit) {\n record({\n name: 'ui-init',\n status: 'skip',\n detail: !answers.withUi\n ? 'withUi = false'\n : 'components.json conflict strategy = skip',\n });\n record({\n name: 'ui-add',\n status: 'skip',\n detail: !answers.withUi\n ? 'withUi = false'\n : 'components.json conflict strategy = skip',\n });\n } else if (dryRun) {\n record({\n name: 'ui-init',\n status: 'planned',\n detail: 'runUiInit()',\n });\n const entries = await resolveUiEntries(options).catch(() => [\n ...BASELINE_UI_ENTRIES,\n ]);\n record({\n name: 'ui-add',\n status: 'planned',\n detail: `runUiAdd(${entries.length} entries: ${entries\n .slice(0, 3)\n .join(', ')}${entries.length > 3 ? '…' : ''})`,\n });\n } else {\n if (aborted) {\n record({\n name: 'ui-init',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n record({\n name: 'ui-add',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n } else {\n let uiInitOk = false;\n try {\n const initResult = await runUiInit({ projectRoot, ide });\n record({\n name: 'ui-init',\n status: 'ok',\n detail:\n initResult.status === 'installed'\n ? 'config.json packages.ui written'\n : initResult.status,\n });\n uiInitOk = true;\n } catch (err) {\n recordFailure('ui-init', err);\n }\n\n if (!uiInitOk) {\n record({\n name: 'ui-add',\n status: 'skip',\n detail: 'aborted: ui-init failed',\n });\n } else if (shadcnDecision === 'skip') {\n record({\n name: 'ui-add',\n status: 'skip',\n detail: 'shadcn-source conflict strategy = skip',\n });\n } else {\n try {\n const entries = await resolveUiEntries(options);\n const addResult = await runUiAdd({\n projectRoot,\n ids: entries,\n // 'overwrite' strategy → overwrite=true; everything else (incl.\n // 'skip-existing' which is the default) → overwrite=false.\n overwrite: shadcnDecision === 'overwrite',\n });\n record({\n name: 'ui-add',\n status: 'ok',\n detail: `${addResult.orderedIds.length} entries (${addResult.written} written, ${addResult.skipped} skipped)`,\n changes: deriveUiAddChanges(addResult, projectRoot),\n });\n } catch (err) {\n recordFailure('ui-add', err);\n }\n }\n }\n }\n recordPending('components-json');\n recordPending('shadcn-source');\n\n // ─── 5. lint ────────────────────────────────────────────────────────────\n if (!answers.withLint) {\n record({\n name: 'lint',\n status: 'skip',\n detail: 'withLint = false',\n });\n } else if (dryRun) {\n record({\n name: 'lint',\n status: 'planned',\n detail: 'runLintInit()',\n });\n } else {\n try {\n // Phase 3.E: forward the wizard's lint conflict decisions so the user\n // can choose `merge` (backup + write template + AI assist) /\n // `backup-overwrite` (legacy) / `skip` (keep user file untouched).\n const eslintStrategy = answers.conflictDecisions['eslint-config'];\n const stylelintStrategy = answers.conflictDecisions['stylelint-config'];\n const eslintExistingPaths = options.legacyEslintPaths ?? [];\n const stylelintExistingPaths = options.legacyStylelintPaths ?? [];\n const result = await runLintInit({\n projectRoot,\n skipInstall: options.skipInstall ?? false,\n eslintStrategy:\n eslintStrategy === 'merge' ||\n eslintStrategy === 'backup-overwrite' ||\n eslintStrategy === 'skip' ||\n eslintStrategy === 'overwrite'\n ? eslintStrategy\n : 'overwrite',\n stylelintStrategy:\n stylelintStrategy === 'merge' ||\n stylelintStrategy === 'backup-overwrite' ||\n stylelintStrategy === 'skip' ||\n stylelintStrategy === 'overwrite'\n ? stylelintStrategy\n : 'overwrite',\n eslintExistingPaths,\n stylelintExistingPaths,\n });\n const detailParts: string[] = [];\n if (result.status === 'installed') {\n detailParts.push(\n `eslint=${result.eslint}, stylelint=${result.stylelint}`,\n );\n if (result.eslintMergeRequested) {\n detailParts.push('eslint:AI-merge-pending');\n }\n if (result.stylelintMergeRequested) {\n detailParts.push('stylelint:AI-merge-pending');\n }\n if (result.eslintSkipped) detailParts.push('eslint:skipped');\n if (result.stylelintSkipped) detailParts.push('stylelint:skipped');\n } else {\n detailParts.push(result.status);\n }\n record({\n name: 'lint',\n status: 'ok',\n detail: detailParts.join(' / '),\n changes: deriveLintChanges(result),\n });\n } catch (err) {\n recordFailure('lint', err);\n }\n }\n\n // ─── tailwind-config / index-css are always pending today (batch 4) ────\n recordPending('tailwind-config');\n recordPending('index-css');\n\n // Phase 1.A1: post-process the change ledger.\n // 1. Diff the backup directory to learn which files were rewritten.\n // 2. Reclassify any matching `created` entries to `modified`.\n // 3. Append a `backed-up` entry per fresh backup so the four-bucket CLI\n // summary stays self-consistent.\n if (!dryRun) {\n try {\n const backupsAfter = await listBackupOriginals(projectRoot);\n const newlyBackedUp = diffBackupSet(backupsBefore, backupsAfter);\n if (newlyBackedUp.size > 0) {\n for (const change of allChanges) {\n if (change.kind === 'created' && newlyBackedUp.has(change.path)) {\n change.kind = 'modified';\n }\n }\n for (const rel of newlyBackedUp) {\n allChanges.push({\n kind: 'backed-up',\n path: rel,\n step: 'backup',\n detail: '.teamix-evo/.backups/<同路径>.<isoTs>.bak',\n });\n }\n }\n } catch {\n // best-effort — ledger is presentation-only, never block init.\n }\n }\n\n const status: RunProjectInitResult['status'] = dryRun\n ? 'dry-run'\n : steps.some((s) => s.status === 'fail')\n ? 'partial'\n : 'installed';\n\n const out: RunProjectInitResult = {\n status,\n steps,\n pendingConflictWork: pending,\n changes: allChanges,\n snapshot,\n };\n if (snapshotError) out.snapshotError = snapshotError;\n\n if (firstFailure.value) {\n out.resumeHint = {\n failedAt: firstFailure.value.step,\n completed: steps.filter((s) => s.status === 'ok').map((s) => s.name),\n failed: steps.filter((s) => s.status === 'fail').map((s) => s.name),\n error: firstFailure.value.error,\n // Every sub-step is idempotent (returns `already-initialized` when its\n // state file already exists), so a plain re-run resumes from the\n // failed step. A richer --resume model lands with batch 3 (lock\n // snapshot + restore).\n resumeCommand: 'teamix-evo init',\n };\n }\n\n return out;\n}\n","/**\n * Programmatic orchestrator for `teamix-evo update` (post-init refresh).\n *\n * Drives the existing per-package update sub-commands (`runTokensUpdate`,\n * `runSkillsUpdate`) in a fixed order, with the same step-by-step reporting\n * + failure-recovery contract used by {@link runProjectInit} (batch 1.2f):\n *\n * - **Critical** steps (`tokens`) abort downstream work on failure — the\n * skills update reads back the project's tokens variant from `config.json`,\n * so a broken tokens update would propagate.\n * - **Non-critical** steps (`skills`) record `fail` but do not block earlier\n * already-completed steps.\n * - On any failure the result includes a {@link ProjectUpdateResumeHint} so\n * the CLI can render a structured recovery message and the caller can\n * re-run `teamix-evo update` (every sub-step is idempotent — version-diff\n * short-circuits when up-to-date).\n *\n * Pre-flight: the project MUST already be teamix-evo-installed (i.e. have\n * `.teamix-evo/config.json`). Empty / non-evo dirs return `not-initialized`\n * so the CLI can route the user to `teamix-evo init` instead.\n *\n * `ui` is intentionally NOT auto-applied by this orchestrator — UI components\n * are frozen (ADR 0019). Per ADR 0040 we DO produce a staging dir under\n * `.teamix-evo/.upgrade-staging/<category>-<ts>/` so the\n * `teamix-evo-upgrade` skill can drive per-file apply later.\n *\n * `ui` / `biz-ui` source-layer upgrades (ADR 0040): produce STAGING ONLY into\n * `.teamix-evo/.upgrade-staging/<category>-<ts>/` — never write into\n * `src/components/{ui,business}/**` (frozen boundary). The `teamix-evo-upgrade`\n * skill consumes the staging and applies per-file with user consent.\n *\n * No interactive prompts, no `process.exit`. Throws on unexpected I/O errors\n * outside the per-step try/catch (P8).\n */\nimport * as path from 'node:path';\nimport {\n loadTokensPackageManifest,\n getVariantEntry,\n} from '@teamix-evo/registry';\nimport type { ProjectConfig, UiAliases } from '@teamix-evo/registry';\nimport { resolveTokensPackageRoot } from '../utils/path.js';\nimport { getErrorMessage } from '../utils/error.js';\nimport { runTokensUpdate } from './tokens-update.js';\nimport { runSkillsUpdate } from './skills-update.js';\nimport { readProjectConfig } from './state.js';\nimport { createSnapshot, type SnapshotResult } from './snapshot.js';\nimport {\n detectComponentLineage,\n type ComponentCategory,\n type ComponentLineageReport,\n} from './ui-upgrade-detector.js';\nimport { buildStaging } from './ui-upgrade.js';\n\nconst DEFAULT_TOKENS_PACKAGE = '@teamix-evo/tokens';\nconst DEFAULT_SKILLS_PACKAGE = '@teamix-evo/skills';\n\nexport type ProjectUpdateStepName = 'tokens' | 'skills' | 'ui' | 'biz-ui';\n\nexport type ProjectUpdateStepStatus = 'ok' | 'skip' | 'fail' | 'planned';\n\nexport interface ProjectUpdateStep {\n name: ProjectUpdateStepName;\n status: ProjectUpdateStepStatus;\n detail?: string;\n}\n\nexport interface ProjectUpdateResumeHint {\n /** The first step that failed (caller resumes from here). */\n failedAt: ProjectUpdateStepName;\n /** Steps already finished (status === 'ok'); will short-circuit on resume. */\n completed: ProjectUpdateStepName[];\n /** All steps that ended in fail status. */\n failed: ProjectUpdateStepName[];\n /** Human-readable error from the first failed step. */\n error: string;\n /**\n * Suggested CLI command to resume. Today this is just `teamix-evo update`\n * itself — every sub-step is idempotent (version-diff short-circuits when\n * up-to-date), so a re-run continues from the failure point automatically.\n */\n resumeCommand: string;\n}\n\nexport interface RunProjectUpdateOptions {\n /** Absolute project root (must already be teamix-evo-installed). */\n projectRoot: string;\n /**\n * If true, plan-only mode: compute version deltas without writing any\n * file. Returns each step with `status: 'planned'`.\n */\n dryRun?: boolean;\n /** Step-level progress hook (caller controls presentation). */\n onStep?: (step: ProjectUpdateStep) => void;\n /** Override the tokens package name (defaults to `@teamix-evo/tokens`). */\n tokensPackageName?: string;\n /** Override the skills package name (defaults to `@teamix-evo/skills`). */\n skillsPackageName?: string;\n}\n\nexport type RunProjectUpdateResult =\n | { status: 'not-initialized' }\n | {\n status: 'up-to-date' | 'updated' | 'partial' | 'dry-run';\n steps: ProjectUpdateStep[];\n resumeHint?: ProjectUpdateResumeHint;\n /**\n * Pre-update snapshot of `.teamix-evo/` ([ADR 0019](../../../../docs/adr/0019-project-upgrade-flow.md) §2).\n * `null` on `dryRun`. Best-effort — capture failures surface via\n * {@link snapshotError} but never abort the pipeline.\n */\n snapshot?: SnapshotResult | null;\n /** Reason a snapshot capture failed (best-effort — never blocks update). */\n snapshotError?: string;\n };\n\n/**\n * Steps whose failure must abort the pipeline (downstream steps depend on\n * the state they write). `tokens` is critical because skills update reads\n * back the variant from `config.json` written by tokens init/update.\n */\nconst CRITICAL_STEPS: ReadonlySet<ProjectUpdateStepName> = new Set(['tokens']);\n\n/**\n * Post-init refresh pipeline.\n *\n * Order:\n * 1. tokens update (regenerable rewrite + frozen preserved — ADR 0003 三态)\n * 2. skills update (lock ∩ scope ∩ version-diff short-circuit — ADR 0035)\n *\n * Re-runs are safe: each sub-step short-circuits when already at latest.\n */\nexport async function runProjectUpdate(\n options: RunProjectUpdateOptions,\n): Promise<RunProjectUpdateResult> {\n const { projectRoot, dryRun = false, onStep } = options;\n const tokensPackage = options.tokensPackageName ?? DEFAULT_TOKENS_PACKAGE;\n const skillsPackage = options.skillsPackageName ?? DEFAULT_SKILLS_PACKAGE;\n\n // ─── Pre-flight ────────────────────────────────────────────────────────\n const config = await readProjectConfig(projectRoot);\n if (!config) {\n return { status: 'not-initialized' };\n }\n\n // ─── Capture pre-update snapshot (ADR 0019 §2) — best-effort ──────────\n // dry-run 不写盘也不拍 snapshot;capture 失败只记录 snapshotError,不 abort 主流程。\n let snapshot: SnapshotResult | null = null;\n let snapshotError: string | undefined;\n if (!dryRun) {\n try {\n snapshot = await createSnapshot(projectRoot, { reason: 'update' });\n } catch (err) {\n snapshotError = getErrorMessage(err);\n }\n }\n\n const steps: ProjectUpdateStep[] = [];\n let aborted = false;\n const firstFailure: {\n value: { step: ProjectUpdateStepName; error: string } | null;\n } = { value: null };\n\n function record(step: ProjectUpdateStep): void {\n steps.push(step);\n onStep?.(step);\n }\n\n function recordFailure(name: ProjectUpdateStepName, err: unknown): void {\n const message = getErrorMessage(err);\n record({ name, status: 'fail', detail: message });\n if (!firstFailure.value) {\n firstFailure.value = { step: name, error: message };\n }\n if (CRITICAL_STEPS.has(name)) aborted = true;\n }\n\n // `anyChanged` only tracks tokens / skills mutations — the two steps that\n // mutate consumer source. ui / biz-ui run in **staging-only** mode (ADR\n // 0040): they emit a dry-run staging dir for the `teamix-evo-upgrade` skill\n // to apply with explicit per-file consent, and intentionally do NOT flip\n // `anyChanged` even when the staging is non-empty. So a run that only\n // produced staging (with tokens / skills already up-to-date) correctly\n // reports `up-to-date` at the project level.\n let anyChanged = false;\n\n // ─── Step 1: tokens ────────────────────────────────────────────────────\n if (!config.packages?.tokens) {\n record({\n name: 'tokens',\n status: 'skip',\n detail: 'tokens not installed',\n });\n } else if (dryRun) {\n try {\n const plan = await planTokensUpdate(tokensPackage, config);\n record({ name: 'tokens', status: 'planned', detail: plan });\n } catch (err) {\n recordFailure('tokens', err);\n }\n } else {\n try {\n const result = await runTokensUpdate({\n projectRoot,\n packageName: tokensPackage,\n });\n if (result.status === 'not-initialized') {\n record({\n name: 'tokens',\n status: 'skip',\n detail: 'tokens not installed',\n });\n } else if (result.status === 'up-to-date') {\n const driftSuffix =\n result.frozenDrift.length > 0\n ? `, frozen drift: ${result.frozenDrift.length}`\n : '';\n record({\n name: 'tokens',\n status: 'ok',\n detail: `up-to-date (${result.variant} v${result.version}${driftSuffix})`,\n });\n } else {\n anyChanged = true;\n const extras: string[] = [];\n if (result.managedReplaced.length > 0)\n extras.push(`managed: ${result.managedReplaced.length}`);\n if (result.frozenDrift.length > 0)\n extras.push(`frozen drift: ${result.frozenDrift.length}`);\n const suffix = extras.length > 0 ? ` [${extras.join(', ')}]` : '';\n record({\n name: 'tokens',\n status: 'ok',\n detail: `${result.variant} v${result.from} → v${result.to}${suffix}`,\n });\n }\n } catch (err) {\n recordFailure('tokens', err);\n }\n }\n\n // ─── Step 2: skills ────────────────────────────────────────────────────\n if (!config.packages?.skills) {\n record({\n name: 'skills',\n status: 'skip',\n detail: 'skills not installed',\n });\n } else if (aborted) {\n record({\n name: 'skills',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n } else {\n try {\n const result = await runSkillsUpdate({\n projectRoot,\n dryRun,\n packageName: skillsPackage,\n });\n if (result.status === 'no-skills') {\n record({\n name: 'skills',\n status: 'skip',\n detail: 'no skills locked',\n });\n } else if (result.status === 'no-changes') {\n record({\n name: 'skills',\n status: 'ok',\n detail: `up-to-date (${result.checkedSkillIds.length} skill(s) at v${result.version})`,\n });\n } else if (result.status === 'dry-run') {\n const bumps = result.plan.filter((p) => p.action === 'version-bump');\n const detail =\n bumps.length === 0\n ? `up-to-date (${result.plan.length} skill(s) checked at v${result.currentVersion})`\n : `${bumps.length} skill(s) would update: ${result.currentVersion} → ${result.availableVersion}`;\n record({ name: 'skills', status: 'planned', detail });\n } else {\n // result.status === 'updated'\n anyChanged = true;\n const summary =\n result.updatedSkillIds.length > 0\n ? `updated: ${result.updatedSkillIds.join(', ')} (v${\n result.version\n })`\n : `refreshed at v${result.version}`;\n record({ name: 'skills', status: 'ok', detail: summary });\n }\n } catch (err) {\n recordFailure('skills', err);\n }\n }\n\n // ─── Step 3: ui (component-source staging — ADR 0040) ───────────────────\n await runComponentSourceStep('ui', {\n projectRoot,\n config,\n dryRun,\n record,\n recordFailure,\n });\n\n // ─── Step 4: biz-ui (component-source staging — ADR 0040) ───────────────\n await runComponentSourceStep('biz-ui', {\n projectRoot,\n config,\n dryRun,\n record,\n recordFailure,\n });\n\n // ─── Build result ──────────────────────────────────────────────────────\n const out: RunProjectUpdateResult = (() => {\n if (firstFailure.value) {\n return {\n status: 'partial' as const,\n steps,\n resumeHint: {\n failedAt: firstFailure.value.step,\n completed: steps.filter((s) => s.status === 'ok').map((s) => s.name),\n failed: steps.filter((s) => s.status === 'fail').map((s) => s.name),\n error: firstFailure.value.error,\n resumeCommand: 'teamix-evo update',\n },\n snapshot,\n ...(snapshotError ? { snapshotError } : {}),\n };\n }\n if (dryRun) return { status: 'dry-run' as const, steps, snapshot: null };\n if (anyChanged)\n return {\n status: 'updated' as const,\n steps,\n snapshot,\n ...(snapshotError ? { snapshotError } : {}),\n };\n return {\n status: 'up-to-date' as const,\n steps,\n snapshot,\n ...(snapshotError ? { snapshotError } : {}),\n };\n })();\n\n return out;\n}\n\n// ─── Helpers ──────────────────────────────────────────────────────\n\n/**\n * Component-source staging step (ADR 0040). Always emits a step record:\n * - `skip` when the package isn't configured / no aliases / lineage absent\n * - `planned` (dry-run) reports what WOULD be staged — no I/O\n * - `ok` writes the staging dir and reports counts\n * - `fail` is non-critical: the upstream pipeline isn't aborted\n *\n * Detect failures → logged as skip (warn-and-skip per plan); only staging\n * write failures escalate to fail.\n */\nasync function runComponentSourceStep(\n category: ComponentCategory,\n args: {\n projectRoot: string;\n config: ProjectConfig;\n dryRun: boolean;\n record: (step: ProjectUpdateStep) => void;\n recordFailure: (name: ProjectUpdateStepName, err: unknown) => void;\n },\n): Promise<void> {\n const { projectRoot, config, dryRun, record, recordFailure } = args;\n const cfgKey = category === 'ui' ? 'ui' : 'biz-ui';\n\n if (!config.packages?.[cfgKey]) {\n record({\n name: category,\n status: 'skip',\n detail: `${category} not installed`,\n });\n return;\n }\n\n // Aliases (UI map) live under packages.ui per ADR 0014; biz-ui shares the\n // same map. Either source is acceptable, ui takes precedence.\n const aliases =\n config.packages.ui?.aliases ??\n (config.packages['biz-ui']?.aliases as UiAliases | undefined);\n if (!aliases) {\n record({\n name: category,\n status: 'skip',\n detail: `${category} aliases not configured`,\n });\n return;\n }\n\n let report: ComponentLineageReport;\n try {\n report = await detectComponentLineage({\n projectRoot,\n category,\n config,\n });\n } catch (err) {\n // Detect failures are warn-and-skip (per plan): keep the orchestrator\n // moving even when the lineage probe trips on disk-state corner cases.\n record({\n name: category,\n status: 'skip',\n detail: `lineage detect failed: ${getErrorMessage(err)}`,\n });\n return;\n }\n\n if (report.lineage !== 'teamix-evo' && report.lineage !== 'mixed') {\n record({\n name: category,\n status: 'skip',\n detail: `lineage=${report.lineage}; nothing to stage`,\n });\n return;\n }\n\n if (dryRun) {\n const total = report.registeredIds.length + report.unregisteredIds.length;\n record({\n name: category,\n status: 'planned',\n detail:\n total === 0\n ? 'no components to stage'\n : `${total} component(s) to stage (lineage=${report.lineage})`,\n });\n return;\n }\n\n try {\n const built = await buildStaging({\n category,\n projectRoot,\n aliases,\n lineageReport: report,\n trigger: 'update',\n onlyIds: [],\n });\n if (built === null) {\n record({\n name: category,\n status: 'skip',\n detail: 'no entries to stage',\n });\n return;\n }\n const stagingRel = path.relative(projectRoot, built.stagingDir);\n const summary = summarizeStagingRisk(built.manifest.summary.byRisk);\n record({\n name: category,\n status: 'ok',\n detail: `${built.manifest.summary.total} component(s) staged${\n summary ? ` (${summary})` : ''\n }, see ${stagingRel}`,\n });\n } catch (err) {\n // Non-critical: doesn't affect tokens / skills already done.\n recordFailure(category, err);\n }\n}\n\nfunction summarizeStagingRisk(byRisk: Record<string, number>): string {\n const order = [\n 'risky',\n 'breaking',\n 'foreign',\n 'upgradable-medium',\n 'upgradable-low',\n 'unchanged',\n ];\n const parts: string[] = [];\n for (const k of order) {\n const v = byRisk[k];\n if (v && v > 0) parts.push(`${v} ${k}`);\n }\n return parts.join(', ');\n}\n\n/**\n * Compute a human-readable plan string for tokens dry-run by comparing the\n * installed version against the upstream catalog. We deliberately do NOT\n * call `runTokensUpdate` here — it lacks a dryRun mode and would write\n * files. The version comparison covers the only thing the user cares about:\n * \"is there a new version, and from where to where\".\n */\nasync function planTokensUpdate(\n tokensPackage: string,\n config: NonNullable<Awaited<ReturnType<typeof readProjectConfig>>>,\n): Promise<string> {\n const tokensCfg = config.packages?.tokens;\n if (!tokensCfg) return 'tokens not installed';\n const packageRoot = resolveTokensPackageRoot(tokensPackage);\n const catalog = await loadTokensPackageManifest(packageRoot);\n const variantEntry = getVariantEntry(catalog, tokensCfg.variant);\n if (!variantEntry) {\n return `variant \"${tokensCfg.variant}\" no longer in ${tokensPackage}@${catalog.version} — uninstall + re-init to switch`;\n }\n if (variantEntry.version === tokensCfg.version) {\n return `up-to-date (${tokensCfg.variant} v${tokensCfg.version})`;\n }\n return `${tokensCfg.variant} v${tokensCfg.version} → v${variantEntry.version}`;\n}\n","/**\n * `teamix-evo tokens update` — refresh tokens with three-state semantics.\n *\n * Per [ADR 0003](../../../../docs/adr/0003-update-strategy-tri-state.md) +\n * [ADR 0019 §D2](../../../../docs/adr/0019-project-upgrade-flow.md), the\n * update is **strategy-driven** off the consumer-side InstalledManifest\n * (recorded at install time):\n *\n * - `regenerable` → upstream content rewrites the file in place.\n * - `managed` → only the marked regions are rewritten via\n * `replaceManagedRegion`; user content outside markers\n * is preserved verbatim. Missing markers in the upstream\n * payload skip that region; missing markers in the\n * consumer file fail loudly (per ADR 0003 Negative — no\n * silent rewrite when anchors are gone).\n * - `frozen` → never overwritten. We still hash-compare upstream vs.\n * the recorded baseline and report \"upstream changed\"\n * drift so the CLI can prompt the user (`--accept-upstream`\n * in a future batch; today we just surface the list).\n *\n * Variant switching is NOT performed here — use `tokens uninstall` then\n * `tokens init <other-variant>`. This command is for in-place version bumps.\n */\nimport * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport {\n loadTokensPackageManifest,\n getVariantEntry,\n type InstalledResource,\n type TokensPackLock,\n type TokenRenameEntry,\n} from '@teamix-evo/registry';\nimport { writeFileSafe, fileExists } from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport {\n readProjectConfig,\n writeProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\nimport {\n selectApplicableRenames,\n writeTokensUpgradeHint,\n} from './upgrade-hints.js';\nimport { resolveTokensPackageRoot } from '../utils/path.js';\nimport { mergeManagedRegions } from './managed-merge.js';\n\nconst DEFAULT_TOKENS_PACKAGE = '@teamix-evo/tokens';\nconst CONSUMER_TOKENS_DIR = 'tokens';\n/** Consumer basename ↔ upstream basename mapping (variants ship `theme.css` / `overrides.css`). */\nconst CONSUMER_BASENAME_BY_UPSTREAM: Record<string, string> = {\n 'theme.css': 'tokens.theme.css',\n 'overrides.css': 'tokens.overrides.css',\n};\n\nexport interface RunTokensUpdateOptions {\n projectRoot: string;\n packageName?: string;\n /** Override resolution of the upstream tokens package root. */\n packageRoot?: string;\n}\n\n/**\n * Per-frozen-resource drift report (ADR 0019 §D2 — surfaced, never\n * auto-applied). Today the only reason we surface is `upstream-changed`:\n * a frozen resource whose upstream content moved since install. Consumer-\n * only files (no upstream counterpart, e.g. an empty `overrides.css`\n * template) are silent — there is nothing to compare against.\n */\nexport interface FrozenDrift {\n /** Consumer-relative path (e.g. `tokens/tokens.overrides.css`). */\n target: string;\n reason: 'upstream-changed';\n}\n\nexport type RunTokensUpdateResult =\n | {\n status: 'updated';\n packageName: string;\n variant: string;\n from: string;\n to: string;\n /** Files fully rewritten (regenerable). */\n rewritten: string[];\n /** Files whose managed regions were replaced. Empty when no managed resource exists. */\n managedReplaced: string[];\n /** Frozen files preserved verbatim. */\n preserved: string[];\n /** Frozen drift hints — surfaced only, never auto-merged. */\n frozenDrift: FrozenDrift[];\n /** Token renames that took effect in this version range (oldest first). */\n renames: TokenRenameEntry[];\n /** Absolute path of the `.teamix-evo/.upgrade-hints/tokens-<ts>.json` file written when `renames` is non-empty. */\n hintPath?: string;\n }\n | {\n status: 'not-initialized';\n }\n | {\n status: 'up-to-date';\n packageName: string;\n variant: string;\n version: string;\n /** Frozen drift may still be reported on `up-to-date` if upstream catalog moved hashes. */\n frozenDrift: FrozenDrift[];\n };\n\nexport async function runTokensUpdate(\n options: RunTokensUpdateOptions,\n): Promise<RunTokensUpdateResult> {\n const { projectRoot } = options;\n const packageName = options.packageName ?? DEFAULT_TOKENS_PACKAGE;\n\n const config = await readProjectConfig(projectRoot);\n if (!config?.packages?.tokens) {\n return { status: 'not-initialized' };\n }\n const currentVariant = config.packages.tokens.variant;\n const currentVersion = config.packages.tokens.version;\n\n const packageRoot =\n options.packageRoot ?? resolveTokensPackageRoot(packageName);\n\n const catalog = await loadTokensPackageManifest(packageRoot);\n const variantEntry = getVariantEntry(catalog, currentVariant);\n if (!variantEntry) {\n throw new Error(\n `Currently installed variant \"${currentVariant}\" no longer exists in ${packageName}@${catalog.version}. ` +\n `Available: ${catalog.variants.map((v) => v.name).join(', ')}. ` +\n `Run \\`npx teamix-evo@latest tokens uninstall\\` then \\`npx teamix-evo@latest tokens init <variant>\\` to switch.`,\n );\n }\n\n // Build upstream basename → absolute path index for strategy dispatch.\n const upstreamByBasename = new Map<string, string>();\n for (const fileRel of variantEntry.files) {\n upstreamByBasename.set(\n path.basename(fileRel),\n path.join(packageRoot, fileRel),\n );\n }\n\n // Pull installed resources for this package — they carry the strategy\n // recorded at install time, which is the dispatch key.\n const prior = (await readInstalledManifest(projectRoot)) ?? {\n schemaVersion: 1 as const,\n installed: [],\n };\n const installedIdx = prior.installed.findIndex(\n (p) => p.package === packageName,\n );\n const priorResources: InstalledResource[] =\n installedIdx >= 0 ? prior.installed[installedIdx]!.resources : [];\n\n const rewritten: string[] = [];\n const managedReplaced: string[] = [];\n const preserved: string[] = [];\n const frozenDrift: FrozenDrift[] = [];\n const refreshedResources: InstalledResource[] = [];\n\n for (const resource of priorResources) {\n const consumerAbs = path.isAbsolute(resource.target)\n ? resource.target\n : path.join(projectRoot, resource.target);\n const consumerBasename = path.basename(resource.target);\n const upstreamBasename = lookupUpstreamBasename(consumerBasename);\n const upstreamAbs = upstreamBasename\n ? upstreamByBasename.get(upstreamBasename)\n : undefined;\n\n if (resource.strategy === 'regenerable') {\n if (!upstreamAbs) {\n // Upstream dropped this regenerable resource — leave the consumer file\n // alone and keep the prior record so removal is the user's call.\n refreshedResources.push(resource);\n continue;\n }\n const content = await fs.readFile(upstreamAbs, 'utf-8');\n await writeFileSafe(consumerAbs, content);\n rewritten.push(resource.target);\n refreshedResources.push({\n ...resource,\n hash: computeHash(content),\n });\n continue;\n }\n\n if (resource.strategy === 'managed') {\n if (!upstreamAbs || !(await fileExists(consumerAbs))) {\n refreshedResources.push(resource);\n continue;\n }\n const upstreamContent = await fs.readFile(upstreamAbs, 'utf-8');\n const consumerContent = await fs.readFile(consumerAbs, 'utf-8');\n const merged = mergeManagedRegions(upstreamContent, consumerContent);\n if (merged !== consumerContent) {\n await writeFileSafe(consumerAbs, merged);\n managedReplaced.push(resource.target);\n }\n refreshedResources.push({\n ...resource,\n hash: computeHash(merged),\n });\n continue;\n }\n\n // strategy === 'frozen' — never overwrite. Surface drift only when an\n // upstream counterpart exists AND its hash moved.\n if (await fileExists(consumerAbs)) preserved.push(resource.target);\n if (upstreamAbs) {\n const upstreamContent = await fs.readFile(upstreamAbs, 'utf-8');\n const upstreamHash = computeHash(upstreamContent);\n if (resource.hash && upstreamHash !== resource.hash) {\n frozenDrift.push({\n target: resource.target,\n reason: 'upstream-changed',\n });\n }\n }\n refreshedResources.push(resource);\n }\n\n // Same-version path: still ran regenerable rewrites + managed merges +\n // collected frozen drift. Report `up-to-date` for clarity but include drift.\n if (variantEntry.version === currentVersion) {\n if (installedIdx >= 0) {\n prior.installed[installedIdx] = {\n ...prior.installed[installedIdx]!,\n resources: refreshedResources,\n };\n await writeInstalledManifest(projectRoot, prior);\n }\n return {\n status: 'up-to-date',\n packageName,\n variant: currentVariant,\n version: currentVersion,\n frozenDrift,\n };\n }\n\n // Version bump path: lock + config + manifest refresh.\n const lock: TokensPackLock = {\n schemaVersion: 1,\n variant: {\n name: variantEntry.name,\n displayName: variantEntry.displayName,\n version: variantEntry.version,\n from: packageName,\n },\n packageVersion: catalog.version,\n linked: variantEntry.linked,\n installedAt: new Date().toISOString(),\n };\n await writeFileSafe(\n path.join(projectRoot, '.teamix-evo', 'tokens-lock.json'),\n JSON.stringify(lock, null, 2) + '\\n',\n );\n\n config.packages.tokens.version = variantEntry.version;\n await writeProjectConfig(projectRoot, config);\n\n if (installedIdx >= 0) {\n prior.installed[installedIdx] = {\n ...prior.installed[installedIdx]!,\n version: variantEntry.version,\n installedAt: new Date().toISOString(),\n resources: refreshedResources,\n };\n await writeInstalledManifest(projectRoot, prior);\n }\n\n // Emit `.teamix-evo/.upgrade-hints/tokens-<ts>.json` when this version\n // bump introduced any token renames (ADR 0019 §D4 — codemod hint, not\n // codemod). Empty rename list → no file written.\n const renames = selectApplicableRenames(\n variantEntry.renames ?? [],\n currentVersion,\n variantEntry.version,\n );\n let hintPath: string | undefined;\n if (renames.length > 0) {\n const hint = await writeTokensUpgradeHint({\n projectRoot,\n trigger: 'update',\n fromVariant: currentVariant,\n toVariant: currentVariant,\n fromVersion: currentVersion,\n toVersion: variantEntry.version,\n renames,\n });\n if (hint) hintPath = hint.path;\n }\n\n return {\n status: 'updated',\n packageName,\n variant: currentVariant,\n from: currentVersion,\n to: variantEntry.version,\n rewritten,\n managedReplaced,\n preserved,\n frozenDrift,\n renames,\n ...(hintPath ? { hintPath } : {}),\n };\n}\n\nfunction lookupUpstreamBasename(consumerBasename: string): string | undefined {\n for (const [upstream, consumer] of Object.entries(\n CONSUMER_BASENAME_BY_UPSTREAM,\n )) {\n if (consumer === consumerBasename) return upstream;\n }\n // managed resources may share basename across upstream/consumer.\n return consumerBasename;\n}\n","/**\n * `.teamix-evo/.upgrade-hints/` writer — emits codemod hint files consumed\n * by the future `teamix-evo-upgrade` skill ([ADR 0019](../../../../docs/adr/0019-project-upgrade-flow.md) §D4).\n *\n * The hint is **passive guidance**: the CLI never auto-rewrites consumer\n * source code (frozen boundary). Hints describe the rename surface so an\n * AI agent / human can scan `src/**` and propose codemods, with the user\n * deciding whether to accept each suggestion.\n *\n * Storage layout:\n * ```\n * .teamix-evo/\n * └── .upgrade-hints/\n * ├── tokens-2026-06-12T03-15-00-000Z.json\n * └── …\n * ```\n *\n * Naming convention: `tokens-<filesystem-safe-iso-ts>.json`. The ts is\n * isoToFsSafe-encoded so directory listings sort chronologically.\n */\nimport * as path from 'node:path';\nimport { writeFileSafe } from '../utils/fs.js';\nimport type { TokenRenameEntry } from '@teamix-evo/registry';\n\nconst TEAMIX_DIR = '.teamix-evo';\nconst HINTS_DIR = '.upgrade-hints';\n\n/** Source of the hint — identifies which command produced it. */\nexport type TokensUpgradeHintTrigger = 'update' | 'switch';\n\n/**\n * Schema of a single `tokens-<ts>.json` hint file. Versioned so we can\n * evolve the shape without breaking older AI skill consumers.\n */\nexport interface TokensUpgradeHint {\n schemaVersion: 1;\n /** ISO timestamp the hint was generated (matches the filename ts). */\n ts: string;\n /** Always `'tokens'` today; reserved for future per-package hints. */\n package: 'tokens';\n /** Which command emitted the hint. */\n trigger: TokensUpgradeHintTrigger;\n /** Variant in effect *before* the operation that produced the hint. */\n fromVariant: string;\n /** Variant in effect *after* the operation. */\n toVariant: string;\n /** Variant version the consumer was on before the operation. */\n fromVersion: string;\n /** Variant version the consumer is on after the operation. */\n toVersion: string;\n /** Rename entries that apply to this transition (ordered by sinceVersion ASC). */\n renames: ReadonlyArray<TokenRenameEntry>;\n}\n\n/**\n * Convert an ISO-8601 timestamp into a filesystem-safe directory / filename\n * fragment. Mirrors `snapshot.isoToFsSafe` — kept private here to avoid a\n * cross-module dependency for one tiny helper.\n */\nfunction isoToFsSafe(iso: string): string {\n return iso.replace(/[:.]/g, '-');\n}\n\nexport interface WriteTokensUpgradeHintOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Trigger that produced the hint. */\n trigger: TokensUpgradeHintTrigger;\n fromVariant: string;\n toVariant: string;\n fromVersion: string;\n toVersion: string;\n /** Pre-filtered rename entries that apply to this transition. */\n renames: ReadonlyArray<TokenRenameEntry>;\n /** Optional ISO ts override (testing hook). Defaults to `new Date().toISOString()`. */\n isoTs?: string;\n}\n\n/**\n * Result of `writeTokensUpgradeHint` — `null` when there were no renames to\n * record (writer skips file creation rather than emit a noisy empty file).\n */\nexport interface TokensUpgradeHintResult {\n /** Absolute path of the written hint file. */\n path: string;\n /** Filesystem-safe ts that appears in the filename. */\n ts: string;\n /** Number of rename entries persisted. */\n renameCount: number;\n}\n\n/**\n * Persist a `tokens-<ts>.json` hint file when there are renames worth\n * surfacing. Returns `null` when `renames` is empty (no-op contract).\n */\nexport async function writeTokensUpgradeHint(\n options: WriteTokensUpgradeHintOptions,\n): Promise<TokensUpgradeHintResult | null> {\n if (options.renames.length === 0) return null;\n\n const isoTs = options.isoTs ?? new Date().toISOString();\n const fsTs = isoToFsSafe(isoTs);\n const filename = `tokens-${fsTs}.json`;\n const target = path.join(\n options.projectRoot,\n TEAMIX_DIR,\n HINTS_DIR,\n filename,\n );\n\n const payload: TokensUpgradeHint = {\n schemaVersion: 1,\n ts: isoTs,\n package: 'tokens',\n trigger: options.trigger,\n fromVariant: options.fromVariant,\n toVariant: options.toVariant,\n fromVersion: options.fromVersion,\n toVersion: options.toVersion,\n renames: options.renames,\n };\n\n await writeFileSafe(target, JSON.stringify(payload, null, 2) + '\\n');\n\n return {\n path: target,\n ts: fsTs,\n renameCount: options.renames.length,\n };\n}\n\n/**\n * Filter a variant's rename log down to the entries that apply when moving\n * from `fromVersion` to `toVersion`. Inclusive of `toVersion`, exclusive of\n * `fromVersion` (the consumer was already on `fromVersion` so any rename\n * recorded at that exact version was already absorbed).\n *\n * Pure semver comparison via numeric splitting (`\\d+\\.\\d+\\.\\d+` shape\n * enforced by `TokenRenameEntrySchema`). Pre-release suffixes use\n * `localeCompare` with `{ numeric: true }` so `rc.10` sorts after `rc.2`\n * (lexicographic comparison is wrong for numeric suffixes).\n */\nexport function selectApplicableRenames(\n renames: ReadonlyArray<TokenRenameEntry>,\n fromVersion: string,\n toVersion: string,\n): TokenRenameEntry[] {\n return renames\n .filter(\n (r) =>\n compareSemver(r.sinceVersion, fromVersion) > 0 &&\n compareSemver(r.sinceVersion, toVersion) <= 0,\n )\n .sort((a, b) => compareSemver(a.sinceVersion, b.sinceVersion));\n}\n\n/**\n * Tri-state semver comparator: returns negative / zero / positive matching\n * the standard `Array.prototype.sort` contract.\n */\nfunction compareSemver(a: string, b: string): number {\n const [aMain = '', aRest = ''] = a.split('-', 2);\n const [bMain = '', bRest = ''] = b.split('-', 2);\n const aParts = aMain.split('.').map((n) => Number.parseInt(n, 10));\n const bParts = bMain.split('.').map((n) => Number.parseInt(n, 10));\n for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {\n const ai = aParts[i] ?? 0;\n const bi = bParts[i] ?? 0;\n if (ai !== bi) return ai - bi;\n }\n // Pre-release suffixes — numeric-aware compare so `rc.10` > `rc.2`;\n // absent suffix > present (per semver §11).\n if (aRest === '' && bRest !== '') return 1;\n if (aRest !== '' && bRest === '') return -1;\n return aRest.localeCompare(bRest, undefined, { numeric: true });\n}\n","import { hasManagedRegion, replaceManagedRegion } from '@teamix-evo/registry';\n\n/**\n * Walk every managed region present in the upstream payload and apply it\n * onto the consumer file. Regions present upstream but missing in the\n * consumer file fail-fast (ADR 0003 Negative — corrupted anchors must not be\n * silently rewritten). Regions absent upstream are left untouched.\n */\nexport function mergeManagedRegions(\n upstreamContent: string,\n consumerContent: string,\n): string {\n let updated = consumerContent;\n const re =\n /<!-- teamix-evo:managed:start id=\"([^\"]+)\" -->([\\s\\S]*?)<!-- teamix-evo:managed:end(?: id=\"\\1\")? -->/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(upstreamContent)) !== null) {\n const id = match[1]!;\n const body = match[2]!.replace(/^\\n/, '').replace(/\\n$/, '');\n if (!hasManagedRegion(updated, id)) {\n throw new Error(\n `Managed region \"${id}\" missing from consumer file — refusing to silently rewrite (ADR 0003).`,\n );\n }\n updated = replaceManagedRegion(updated, id, body);\n }\n return updated;\n}\n","/**\n * Component-source upgrade lineage detector ([ADR 0040](../../../../docs/adr/0040-component-source-layer-upgrade-flow.md) §D1).\n *\n * Classifies the consumer project's `ui` / `biz-ui` directory into one of four\n * lineage buckets so the upgrade pipeline (and downstream skill) can choose\n * the right opening line + bucket strategy:\n *\n * | lineage | criterion |\n * | --------------- | --------------------------------------------------------------------------- |\n * | `teamix-evo` | manifest has the package, every on-disk file is registered |\n * | `mixed` | manifest has the package, but extra unregistered files exist on disk |\n * | `shadcn-native` | manifest lacks the package, `components.json` exists, on-disk files exist |\n * | `custom-only` | manifest lacks the package, no `components.json`, on-disk files exist |\n * | `absent` | none of the above — nothing to upgrade |\n *\n * Pure read-only — never mutates the filesystem.\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n ComponentLineage,\n InstalledManifest,\n InstalledPackage,\n ProjectConfig,\n UiAliases,\n} from '@teamix-evo/registry';\nimport { fileExists } from '../utils/fs.js';\nimport {\n findInstalledPackage,\n readInstalledManifest,\n readProjectConfig,\n} from './state.js';\nimport { DEFAULT_UI_ALIASES } from './ui-init.js';\n\n/** Which package category to detect lineage for. */\nexport type ComponentCategory = 'ui' | 'biz-ui';\n\n/** Lineage classification including the special `absent` bucket. */\nexport type ComponentLineageWithAbsent = ComponentLineage | 'absent';\n\nconst PACKAGE_NAME: Record<ComponentCategory, string> = {\n ui: '@teamix-evo/ui',\n 'biz-ui': '@teamix-evo/biz-ui',\n};\n\nconst ALIAS_KEY: Record<ComponentCategory, keyof UiAliases> = {\n ui: 'components',\n 'biz-ui': 'business',\n};\n\n/** Files matching this regex inside the install dir are considered components. */\nconst COMPONENT_FILE_RE = /\\.(tsx|ts)$/;\n\n/** Filenames that are conventional helpers and should NOT be counted as components. */\nconst SKIP_FILENAMES = new Set(['index.ts', 'index.tsx']);\n\nexport interface ComponentLineageReport {\n /** Which package category this report describes. */\n category: ComponentCategory;\n /** Bucket assignment per the table above. */\n lineage: ComponentLineageWithAbsent;\n /** Resolved install dir (project-relative, e.g. `src/components/ui`). */\n installDir: string;\n /** Whether the install dir exists on disk. */\n installDirExists: boolean;\n /** Whether `components.json` exists at project root. */\n hasComponentsJson: boolean;\n /** Component ids registered in `.teamix-evo/manifest.json` (e.g. `[\"button\", \"input\"]`). */\n registeredIds: string[];\n /** Component ids found on disk but absent from the installed manifest. */\n unregisteredIds: string[];\n /** Installed package version, or null if the package is not in the manifest. */\n installedVersion: string | null;\n /** Variant: `'_flat'` for ui; concrete variant id (e.g. `'opentrek'`) for biz-ui; null when not installed. */\n installedVariant: string | null;\n}\n\nexport interface DetectComponentLineageOptions {\n projectRoot: string;\n category: ComponentCategory;\n /**\n * Optional pre-loaded project config. When omitted the detector reads it\n * from `.teamix-evo/config.json` itself; supplying it avoids redundant I/O\n * when the caller already holds one (e.g. `runProjectUpdate`).\n */\n config?: ProjectConfig | null;\n /**\n * Optional pre-loaded installed manifest. Same rationale as `config`.\n */\n installed?: InstalledManifest | null;\n}\n\n/**\n * Detect component-source lineage for the given project + category.\n *\n * Always returns a report — `lineage: 'absent'` when nothing to do, never\n * throws on an empty directory.\n */\nexport async function detectComponentLineage(\n options: DetectComponentLineageOptions,\n): Promise<ComponentLineageReport> {\n const { projectRoot, category } = options;\n const config = options.config ?? (await readProjectConfig(projectRoot));\n const installed =\n options.installed ?? (await readInstalledManifest(projectRoot));\n\n const installDir = resolveInstallDir(category, config);\n const installDirAbs = path.join(projectRoot, installDir);\n const installDirExists = await directoryExists(installDirAbs);\n const hasComponentsJson = await fileExists(\n path.join(projectRoot, 'components.json'),\n );\n\n const installedPkg = findInstalledPackage(installed, PACKAGE_NAME[category]);\n const registeredIds = installedPkg ? extractIds(installedPkg).sort() : [];\n\n const onDiskIds = installDirExists\n ? await listComponentIds(installDirAbs)\n : [];\n const registeredSet = new Set(registeredIds);\n const unregisteredIds = onDiskIds\n .filter((id) => !registeredSet.has(id))\n .sort();\n\n const lineage = classifyLineage({\n hasInstalled: installedPkg !== null,\n hasComponentsJson,\n onDiskIds,\n unregisteredIds,\n });\n\n return {\n category,\n lineage,\n installDir,\n installDirExists,\n hasComponentsJson,\n registeredIds,\n unregisteredIds,\n installedVersion: installedPkg?.version ?? null,\n installedVariant: installedPkg?.variant ?? null,\n };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction resolveInstallDir(\n category: ComponentCategory,\n config: ProjectConfig | null,\n): string {\n // ui aliases live under packages.ui (per ui-init); biz-ui shares the same\n // alias map (UiAliasesSchema includes the `business` field).\n const aliasMap =\n config?.packages?.ui?.aliases ??\n (config?.packages?.['biz-ui']?.aliases as UiAliases | undefined) ??\n DEFAULT_UI_ALIASES;\n const key = ALIAS_KEY[category];\n return aliasMap[key] ?? DEFAULT_UI_ALIASES[key];\n}\n\n/**\n * Extract distinct component ids from an installed package's resources.\n * `InstalledResource.id` is shaped `\"<entryId>:<filename>\"` (see\n * `ui-installer.ts` L111). We collapse on the entryId portion so a multi-file\n * entry (rare) only shows up once.\n */\nfunction extractIds(pkg: InstalledPackage): string[] {\n const ids = new Set<string>();\n for (const r of pkg.resources) {\n const colon = r.id.indexOf(':');\n ids.add(colon >= 0 ? r.id.slice(0, colon) : r.id);\n }\n return [...ids];\n}\n\nasync function directoryExists(p: string): Promise<boolean> {\n try {\n const stat = await fs.stat(p);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\n/**\n * List component ids on disk. Strips the file extension; skips `index.{ts,tsx}`\n * and any nested directories (entry sources are flattened by ui-installer).\n */\nasync function listComponentIds(installDirAbs: string): Promise<string[]> {\n const entries = await fs.readdir(installDirAbs, { withFileTypes: true });\n const ids: string[] = [];\n for (const e of entries) {\n if (!e.isFile()) continue;\n if (SKIP_FILENAMES.has(e.name)) continue;\n if (!COMPONENT_FILE_RE.test(e.name)) continue;\n ids.push(e.name.replace(COMPONENT_FILE_RE, ''));\n }\n return ids.sort();\n}\n\ninterface ClassifyArgs {\n hasInstalled: boolean;\n hasComponentsJson: boolean;\n onDiskIds: string[];\n unregisteredIds: string[];\n}\n\nfunction classifyLineage(args: ClassifyArgs): ComponentLineageWithAbsent {\n const { hasInstalled, hasComponentsJson, onDiskIds, unregisteredIds } = args;\n if (hasInstalled) {\n return unregisteredIds.length === 0 ? 'teamix-evo' : 'mixed';\n }\n // Not installed via teamix-evo.\n if (onDiskIds.length === 0) return 'absent';\n return hasComponentsJson ? 'shadcn-native' : 'custom-only';\n}\n","/**\n * Programmatic core for `teamix-evo ui upgrade` / `teamix-evo biz-ui upgrade`\n * ([ADR 0040](../../../../docs/adr/0040-component-source-layer-upgrade-flow.md) §D5).\n *\n * The CLI command delegates here; the project-update orchestrator also reuses\n * `buildComponentSourceStaging` so the same staging shape is produced by both\n * paths. Frozen boundary preserved: this module **never writes** into\n * `src/components/{ui,business}/**`. The skill consumes the staging.\n */\nimport * as path from 'node:path';\nimport { createRequire } from 'node:module';\nimport {\n loadUiPackageManifest,\n loadVariantUiPackageManifest,\n} from '@teamix-evo/registry';\nimport type {\n UiAliases,\n UiEntry,\n UiPackageManifest,\n UpgradeStagingManifest,\n UpgradeStagingTrigger,\n} from '@teamix-evo/registry';\nimport { readProjectConfig, readInstalledManifest } from './state.js';\nimport {\n detectComponentLineage,\n type ComponentCategory,\n type ComponentLineageReport,\n} from './ui-upgrade-detector.js';\nimport {\n buildUiUpgradeStaging,\n type BuildUiUpgradeStagingResult,\n} from './ui-upgrade-staging.js';\n\nconst nodeRequire = createRequire(import.meta.url);\n\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = nodeRequire.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\nexport interface RunUiUpgradeOptions {\n /** Absolute project root. */\n projectRoot: string;\n /** Which package category to stage. */\n category: ComponentCategory;\n /**\n * Restrict to a subset of entry ids. Empty / undefined → all registered ids\n * (plus foreign ids in `mixed` lineage).\n */\n ids?: string[];\n /** Trigger label written into the staging manifest. */\n trigger: UpgradeStagingTrigger;\n /** Override package roots (test hook). */\n uiPackageRoot?: string;\n bizUiPackageRoot?: string;\n}\n\nexport type RunUiUpgradeResult =\n | {\n status: 'not-initialized';\n }\n | {\n status: 'not-installed';\n detail: string;\n }\n | {\n status: 'skipped';\n detail: string;\n lineage: ComponentLineageReport['lineage'];\n }\n | {\n status: 'staged';\n stagingDir: string;\n manifest: UpgradeStagingManifest;\n };\n\n/**\n * High-level orchestration:\n *\n * 1. Read project config (must be teamix-evo-installed)\n * 2. Detect lineage for the requested category\n * 3. Resolve upstream manifest (variant-aware for biz-ui)\n * 4. Delegate to `buildUiUpgradeStaging`\n *\n * Throws only on programming errors; expected user-facing failures (no\n * config, package not installed, unknown id) are surfaced via the discriminated\n * return type so the CLI / orchestrator can render them consistently.\n */\nexport async function runUiUpgrade(\n options: RunUiUpgradeOptions,\n): Promise<RunUiUpgradeResult> {\n const { projectRoot, category, ids = [], trigger } = options;\n\n const config = await readProjectConfig(projectRoot);\n if (!config) return { status: 'not-initialized' };\n\n const cfgKey = category === 'ui' ? 'ui' : 'biz-ui';\n if (!config.packages?.[cfgKey]) {\n return { status: 'not-installed', detail: `${category} not installed` };\n }\n\n // ui aliases live under packages.ui per ADR 0014; biz-ui shares the map.\n const aliases =\n config.packages.ui?.aliases ??\n (config.packages['biz-ui']?.aliases as UiAliases | undefined);\n if (!aliases) {\n return {\n status: 'not-installed',\n detail: `${category} aliases not configured (run \\`teamix-evo ui init\\` first)`,\n };\n }\n\n const installed = await readInstalledManifest(projectRoot);\n const lineageReport = await detectComponentLineage({\n projectRoot,\n category,\n config,\n installed,\n });\n\n if (\n lineageReport.lineage !== 'teamix-evo' &&\n lineageReport.lineage !== 'mixed'\n ) {\n return {\n status: 'skipped',\n detail: `lineage=${lineageReport.lineage}; nothing to stage`,\n lineage: lineageReport.lineage,\n };\n }\n\n // Validate that explicit ids are recognised — surface a clear error rather\n // than silently producing an empty staging dir.\n if (ids.length > 0) {\n const knownIds = new Set([\n ...lineageReport.registeredIds,\n ...lineageReport.unregisteredIds,\n ]);\n const unknown = ids.filter((id) => !knownIds.has(id));\n if (unknown.length > 0) {\n throw new Error(\n `Unknown ${category} component id(s): ${unknown\n .map((s) => `\"${s}\"`)\n .join(\n ', ',\n )}. Hint: \\`teamix-evo ${category} list\\` shows available ids.`,\n );\n }\n }\n\n const built = await buildStaging({\n category,\n projectRoot,\n aliases,\n lineageReport,\n trigger,\n onlyIds: ids,\n uiPackageRoot: options.uiPackageRoot,\n bizUiPackageRoot: options.bizUiPackageRoot,\n });\n\n if (built === null) {\n return {\n status: 'skipped',\n detail: 'no entries to stage',\n lineage: lineageReport.lineage,\n };\n }\n\n return {\n status: 'staged',\n stagingDir: built.stagingDir,\n manifest: built.manifest,\n };\n}\n\ninterface BuildStagingArgs {\n category: ComponentCategory;\n projectRoot: string;\n aliases: UiAliases;\n lineageReport: ComponentLineageReport;\n trigger: UpgradeStagingTrigger;\n onlyIds: string[];\n uiPackageRoot?: string;\n bizUiPackageRoot?: string;\n}\n\n/**\n * Resolve upstream manifest + (for biz-ui) merge cross-package deps from\n * `@teamix-evo/ui`, then delegate to `buildUiUpgradeStaging`. Exposed so the\n * project-update orchestrator can reuse the exact same code path.\n */\nexport async function buildStaging(\n args: BuildStagingArgs,\n): Promise<BuildUiUpgradeStagingResult | null> {\n const { category, projectRoot, aliases, lineageReport, trigger, onlyIds } =\n args;\n if (category === 'ui') {\n const root = args.uiPackageRoot ?? resolvePackageRoot('@teamix-evo/ui');\n const manifest = await loadUiPackageManifest(root);\n return buildUiUpgradeStaging({\n projectRoot,\n category,\n manifest,\n packageRoot: root,\n aliases,\n lineageReport,\n trigger,\n onlyIds,\n });\n }\n\n // biz-ui — merge variant entries with @teamix-evo/ui entries (for transitive\n // ui deps that may have landed under biz-ui's installed record). Mirrors\n // `runVariantUiAdd` so the same dep graph applies.\n const bizRoot =\n args.bizUiPackageRoot ?? resolvePackageRoot('@teamix-evo/biz-ui');\n const variant = lineageReport.installedVariant ?? '_flat';\n const variantDir = path.join(bizRoot, 'variants', variant);\n const variantManifest = await loadVariantUiPackageManifest(variantDir);\n const uiRoot = args.uiPackageRoot ?? resolvePackageRoot('@teamix-evo/ui');\n const uiManifest = await loadUiPackageManifest(uiRoot);\n\n const entryPackageRoot = new Map<string, string>();\n const merged: UiEntry[] = [];\n for (const e of variantManifest.entries) {\n entryPackageRoot.set(e.id, variantDir);\n merged.push(e);\n }\n for (const e of uiManifest.entries) {\n if (entryPackageRoot.has(e.id)) continue;\n entryPackageRoot.set(e.id, uiRoot);\n merged.push(e);\n }\n\n const synthetic: UiPackageManifest = {\n schemaVersion: 1,\n package: 'ui',\n version: variantManifest.version,\n engines: variantManifest.engines,\n entries: merged,\n };\n\n return buildUiUpgradeStaging({\n projectRoot,\n category,\n manifest: synthetic,\n packageRoot: variantDir,\n entryPackageRoot,\n aliases,\n lineageReport,\n trigger,\n onlyIds,\n });\n}\n","/**\n * Component-source upgrade staging builder ([ADR 0040](../../../../docs/adr/0040-component-source-layer-upgrade-flow.md) §D2-D4).\n *\n * Given a lineage report (from `ui-upgrade-detector`) and the upstream package\n * manifest + root, produces a `.teamix-evo/.upgrade-staging/<category>-<ts>/`\n * directory containing:\n *\n * - `meta.json` — {@link UpgradeStagingManifest} payload (the truth source)\n * - `<id>/current.{tsx,ts}` — copy of the consumer's installed file\n * - `<id>/incoming.{tsx,ts}`— upstream source after applying the consumer's import-rewrite aliases\n *\n * Pure produce-only — never writes into `src/components/{ui,business}/**`\n * (frozen boundary preserved). The staging dir is consumed by the\n * `teamix-evo-upgrade` skill, which decides per-file apply with user consent.\n *\n * Risk classification uses regex-level heuristics (no AST) — the skill is\n * expected to refine the level after reading the staged sources.\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport type {\n InstalledManifest,\n InstalledPackage,\n InstalledResource,\n PromoteFeatureVector,\n PromoteFileType,\n PromoteMode,\n UiAliases,\n UiEntry,\n UiPackageManifest,\n UpgradeRiskLevel,\n UpgradeStagingDiff,\n UpgradeStagingEntry,\n UpgradeStagingManifest,\n UpgradeStagingPromotion,\n UpgradeStagingTrigger,\n} from '@teamix-evo/registry';\nimport {\n writeFileSafe,\n ensureDir,\n readFileOrNull,\n fileExists,\n} from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport { rewriteImports } from '../utils/transform-imports.js';\nimport { findInstalledPackage, readInstalledManifest } from './state.js';\nimport type {\n ComponentCategory,\n ComponentLineageReport,\n} from './ui-upgrade-detector.js';\n\nconst TEAMIX_DIR = '.teamix-evo';\nconst STAGING_DIR = '.upgrade-staging';\n\nconst PACKAGE_NAME: Record<ComponentCategory, string> = {\n ui: '@teamix-evo/ui',\n 'biz-ui': '@teamix-evo/biz-ui',\n};\n\n/** Match `iso-to-fs-safe` used by `upgrade-hints.ts` so dirs sort chronologically. */\nfunction isoToFsSafe(iso: string): string {\n return iso.replace(/[:.]/g, '-');\n}\n\nexport interface BuildUiUpgradeStagingOptions {\n /** Absolute project root. */\n projectRoot: string;\n /** Which category this run targets. */\n category: ComponentCategory;\n /**\n * Upstream package manifest (already loaded by the caller — avoids forcing\n * this module to know about variant resolution; the caller adapts variant\n * manifests via `loadVariantUiPackageManifest` and synthesizes a\n * `UiPackageManifest` shape per `variant-ui-add.ts`).\n */\n manifest: UiPackageManifest;\n /** Absolute upstream package root (where `entry.files[].source` resolves). */\n packageRoot: string;\n /**\n * Optional per-entry root override — used by biz-ui where some entries come\n * from the variant dir and cross-package deps come from `@teamix-evo/ui`.\n */\n entryPackageRoot?: Map<string, string>;\n /** Consumer-side alias map (from `config.packages.ui.aliases`). */\n aliases: UiAliases;\n /** Pre-computed lineage report for this category. */\n lineageReport: ComponentLineageReport;\n /** Which command produced the staging. */\n trigger: UpgradeStagingTrigger;\n /** Restrict processing to a subset of entry ids (single-component path). */\n onlyIds?: string[];\n /** Pre-loaded installed manifest (to avoid double I/O when caller has it). */\n installed?: InstalledManifest | null;\n /** Testing hook — fixed iso ts so the staging dir name is deterministic. */\n isoTs?: string;\n}\n\nexport interface BuildUiUpgradeStagingResult {\n /** Absolute staging dir path (`.teamix-evo/.upgrade-staging/<category>-<ts>/`). */\n stagingDir: string;\n /** The manifest payload that was written to `meta.json`. */\n manifest: UpgradeStagingManifest;\n}\n\n/**\n * Build a staging dir + manifest. Returns `null` when there is nothing to\n * stage (no installed package for this category, or all entries filtered out).\n */\nexport async function buildUiUpgradeStaging(\n options: BuildUiUpgradeStagingOptions,\n): Promise<BuildUiUpgradeStagingResult | null> {\n const { lineageReport, category } = options;\n\n // Lineages without an installed teamix-evo package have nothing to compare\n // against. shadcn-native / custom-only / absent are no-ops here — they are\n // handled by the skill (migration suggestions), not by staging.\n if (\n lineageReport.lineage !== 'teamix-evo' &&\n lineageReport.lineage !== 'mixed'\n ) {\n return null;\n }\n\n const installed =\n options.installed ?? (await readInstalledManifest(options.projectRoot));\n const installedPkg = findInstalledPackage(installed, PACKAGE_NAME[category]);\n if (!installedPkg) return null;\n\n const isoTs = options.isoTs ?? new Date().toISOString();\n const fsTs = isoToFsSafe(isoTs);\n const stagingDir = path.join(\n options.projectRoot,\n TEAMIX_DIR,\n STAGING_DIR,\n `${category}-${fsTs}`,\n );\n\n const entryMap = new Map<string, UiEntry>(\n options.manifest.entries.map((e) => [e.id, e]),\n );\n\n // First installed resource per entry id (multi-file entries are rare; we\n // stage the primary file and emit a hint when extras exist).\n const resByEntryId = collectResourcesByEntry(installedPkg.resources);\n\n const onlyIds =\n options.onlyIds && options.onlyIds.length > 0\n ? new Set(options.onlyIds)\n : null;\n\n const entries: UpgradeStagingEntry[] = [];\n\n // ─── Registered ids (have installed records) ─────────────────────────────\n for (const id of lineageReport.registeredIds) {\n if (onlyIds && !onlyIds.has(id)) continue;\n const built = await processRegistered({\n id,\n entry: entryMap.get(id),\n resource: resByEntryId.get(id),\n packageRoot: options.packageRoot,\n entryPackageRoot: options.entryPackageRoot,\n aliases: options.aliases,\n stagingDir,\n projectRoot: options.projectRoot,\n category,\n sourceVersion: options.manifest.version,\n });\n if (built) entries.push(built);\n }\n\n // ─── Foreign ids (mixed lineage extras) ──────────────────────────────────\n for (const id of lineageReport.unregisteredIds) {\n if (onlyIds && !onlyIds.has(id)) continue;\n const built = await processForeign({\n id,\n installDirAbs: path.join(options.projectRoot, lineageReport.installDir),\n stagingDir,\n projectRoot: options.projectRoot,\n category,\n });\n if (built) entries.push(built);\n }\n\n if (entries.length === 0) return null;\n\n const byRisk = aggregateByRisk(entries);\n const manifestOut: UpgradeStagingManifest = {\n schemaVersion: 1,\n ts: isoTs,\n package: category,\n trigger: options.trigger,\n variant: lineageReport.installedVariant ?? '_flat',\n fromVersion: lineageReport.installedVersion ?? '',\n toVersion: options.manifest.version,\n lineage: lineageReport.lineage,\n summary: { total: entries.length, byRisk },\n entries,\n };\n\n await ensureDir(stagingDir);\n await writeFileSafe(\n path.join(stagingDir, 'meta.json'),\n JSON.stringify(manifestOut, null, 2) + '\\n',\n );\n\n return { stagingDir, manifest: manifestOut };\n}\n\n// ─── Per-entry processors ────────────────────────────────────────────────────\n\ninterface ProcessRegisteredArgs {\n id: string;\n entry: UiEntry | undefined;\n resource: InstalledResource | undefined;\n packageRoot: string;\n entryPackageRoot?: Map<string, string>;\n aliases: UiAliases;\n stagingDir: string;\n projectRoot: string;\n category: ComponentCategory;\n sourceVersion: string;\n}\n\nasync function processRegistered(\n args: ProcessRegisteredArgs,\n): Promise<UpgradeStagingEntry | null> {\n const { id, entry, resource, stagingDir, projectRoot, category } = args;\n if (!resource) return null;\n\n const currentSource = await readFileOrNull(resource.target);\n // File present in installed manifest but missing on disk — surface as\n // breaking so the AI can reconcile (likely user deleted the file).\n if (currentSource === null) {\n return buildBreakingEntry({\n id,\n category,\n resource,\n projectRoot,\n stagingDir,\n currentSource: '',\n hint: 'installed file missing on disk',\n });\n }\n\n // Upstream removed this entry — breaking, emit current.tsx only.\n if (!entry) {\n return buildBreakingEntry({\n id,\n category,\n resource,\n projectRoot,\n stagingDir,\n currentSource,\n hint: 'entry removed in upstream package',\n });\n }\n\n const file = entry.files[0];\n if (!file) return null;\n\n const rootForEntry = args.entryPackageRoot?.get(id) ?? args.packageRoot;\n const sourceAbs = path.resolve(rootForEntry, file.source);\n const raw = await readFileOrNull(sourceAbs);\n if (raw === null) {\n // Upstream manifest references a missing file — degenerate; skip rather\n // than fail the whole pipeline.\n return null;\n }\n const incomingTransformed = rewriteImports(raw, args.aliases);\n const incomingHash = computeHash(incomingTransformed);\n\n const currentExt = path.extname(resource.target) || '.tsx';\n const incomingExt = path.extname(file.targetName) || currentExt;\n const currentRel = `${id}/current${currentExt}`;\n const incomingRel = `${id}/incoming${incomingExt}`;\n await writeFileSafe(path.join(stagingDir, currentRel), currentSource);\n await writeFileSafe(path.join(stagingDir, incomingRel), incomingTransformed);\n\n const diff = classifyRisk({\n currentHash: resource.hash,\n incomingHash,\n currentSource,\n incomingSource: incomingTransformed,\n multiFile: entry.files.length > 1,\n });\n\n const promotion = derivePromotion({\n currentSource,\n incomingSource: incomingTransformed,\n targetName: entry.files[0]?.targetName ?? `${id}.tsx`,\n });\n\n return {\n id,\n category,\n current: {\n target: path.relative(projectRoot, resource.target),\n hash: resource.hash,\n sourceLineage: 'teamix-evo',\n },\n incoming: {\n sourceVersion: args.sourceVersion,\n hash: incomingHash,\n relPath: incomingRel,\n },\n diff,\n promotion,\n };\n}\n\ninterface ProcessForeignArgs {\n id: string;\n installDirAbs: string;\n stagingDir: string;\n projectRoot: string;\n category: ComponentCategory;\n}\n\nasync function processForeign(\n args: ProcessForeignArgs,\n): Promise<UpgradeStagingEntry | null> {\n const { id, installDirAbs, stagingDir, projectRoot, category } = args;\n const tsx = path.join(installDirAbs, `${id}.tsx`);\n const ts = path.join(installDirAbs, `${id}.ts`);\n const target = (await fileExists(tsx))\n ? tsx\n : (await fileExists(ts))\n ? ts\n : null;\n if (!target) return null;\n\n const raw = await readFileOrNull(target);\n if (raw === null) return null;\n\n const ext = path.extname(target);\n const currentRel = `${id}/current${ext}`;\n await writeFileSafe(path.join(stagingDir, currentRel), raw);\n\n return {\n id,\n category,\n current: {\n target: path.relative(projectRoot, target),\n hash: computeHash(raw),\n sourceLineage: 'custom',\n },\n diff: {\n riskLevel: 'foreign',\n hints: [\n 'component is on disk but not registered in .teamix-evo/manifest.json',\n 'AI should propose: (a) ignore, (b) re-register via teamix-evo ui add, or (c) remove',\n ],\n filesChangedCount: 0,\n },\n };\n}\n\ninterface BuildBreakingArgs {\n id: string;\n category: ComponentCategory;\n resource: InstalledResource;\n projectRoot: string;\n stagingDir: string;\n currentSource: string;\n hint: string;\n}\n\nasync function buildBreakingEntry(\n args: BuildBreakingArgs,\n): Promise<UpgradeStagingEntry> {\n const ext = path.extname(args.resource.target) || '.tsx';\n const currentRel = `${args.id}/current${ext}`;\n // Always materialize the current snapshot so the AI can reason even when\n // the source disappeared from disk (zero-byte file is still informative).\n await writeFileSafe(\n path.join(args.stagingDir, currentRel),\n args.currentSource,\n );\n return {\n id: args.id,\n category: args.category,\n current: {\n target: path.relative(args.projectRoot, args.resource.target),\n hash: args.resource.hash,\n sourceLineage: 'teamix-evo',\n },\n diff: {\n riskLevel: 'breaking',\n hints: [args.hint],\n filesChangedCount: 0,\n },\n };\n}\n\n// ─── Risk classifier ─────────────────────────────────────────────────────────\n\ninterface ClassifyRiskArgs {\n currentHash: string;\n incomingHash: string;\n currentSource: string;\n incomingSource: string;\n multiFile: boolean;\n}\n\n/**\n * Lightweight risk classifier — regex-level only (per ADR 0040 §D3). The\n * skill is expected to refine after reading the staged sources, but the\n * default level lets the AI summarize \"X risky / Y medium / Z low\" without\n * reading any source code.\n */\nfunction classifyRisk(args: ClassifyRiskArgs): UpgradeStagingDiff {\n if (args.currentHash === args.incomingHash) {\n return { riskLevel: 'unchanged', hints: [], filesChangedCount: 0 };\n }\n\n const curExports = extractExportNames(args.currentSource);\n const newExports = extractExportNames(args.incomingSource);\n // Risk-classification perspective: \"removed\" = upstream dropped an export\n // the user still relied on; \"added\" = upstream introduced a new symbol.\n // (Compare to buildFeatureVector below which uses the user's perspective.)\n const removedExports = setDiff(curExports, newExports);\n const addedExports = setDiff(newExports, curExports);\n\n const curVariants = extractCvaVariantValues(args.currentSource);\n const newVariants = extractCvaVariantValues(args.incomingSource);\n const removedVariants = setDiff(curVariants, newVariants);\n const addedVariants = setDiff(newVariants, curVariants);\n\n const hints: string[] = [];\n for (const e of removedExports) hints.push(`removed export: ${e}`);\n for (const e of addedExports) hints.push(`new export: ${e}`);\n for (const v of removedVariants) hints.push(`removed cva variant: ${v}`);\n for (const v of addedVariants) hints.push(`new cva variant: ${v}`);\n if (args.multiFile) hints.push('multi-file entry; only first file staged');\n\n let riskLevel: UpgradeRiskLevel;\n if (removedExports.length > 0 || removedVariants.length > 0) {\n riskLevel = 'risky';\n } else if (\n addedExports.length > 0 ||\n addedVariants.length > 0 ||\n args.multiFile\n ) {\n riskLevel = 'upgradable-medium';\n } else {\n riskLevel = 'upgradable-low';\n }\n\n return { riskLevel, hints, filesChangedCount: 1 };\n}\n\n/**\n * Best-effort export-name extractor (regex). Catches `export const Foo`,\n * `export function Foo`, `export class Foo`, `export interface Foo`,\n * `export type Foo`, `export enum Foo`, and `export default <Identifier>`.\n * Misses re-exports (`export { X } from`) — those are rare for ui entries\n * and would require AST-level analysis to do correctly.\n */\nfunction extractExportNames(src: string): string[] {\n const names = new Set<string>();\n const re =\n /^\\s*export\\s+(?:default\\s+)?(?:async\\s+)?(?:const|let|var|function|class|interface|type|enum)\\s+(\\w+)/gm;\n let m: RegExpExecArray | null;\n while ((m = re.exec(src)) !== null) {\n if (m[1]) names.add(m[1]);\n }\n // `export default Foo` (referenced identifier, not a declaration)\n for (const dm of src.matchAll(/^\\s*export\\s+default\\s+(\\w+)\\s*;/gm)) {\n if (dm[1]) names.add(dm[1]);\n }\n return [...names];\n}\n\n/**\n * Extract value-level cva variant keys (e.g. `default`, `ghost`, `destructive`).\n * Looks for a `variants: { ... }` object literal and harvests the second-level\n * keys inside each named group (`variant: { default: ..., ghost: ... }`).\n *\n * Naive, two-step regex:\n * 1. Locate the outermost `variants: { ... }` block via balanced-brace scan.\n * 2. For each top-level group `<name>: { ... }`, harvest its inner keys.\n *\n * Returns the union of inner keys across all groups (a single name like\n * `ghost` showing up in two groups still counts as one).\n */\nfunction extractCvaVariantValues(src: string): string[] {\n const block = extractVariantsBlock(src);\n if (block === null) return [];\n const names = new Set<string>();\n for (const groupBody of extractGroupBodies(block)) {\n for (const km of groupBody.matchAll(/^\\s*(?:['\"]?)(\\w+)(?:['\"]?)\\s*:/gm)) {\n if (km[1]) names.add(km[1]);\n }\n }\n return [...names];\n}\n\n/** Brace-balanced extraction of the body inside `variants: { ... }`. */\nfunction extractVariantsBlock(src: string): string | null {\n const idx = src.search(/\\bvariants\\s*:\\s*\\{/);\n if (idx < 0) return null;\n const open = src.indexOf('{', idx);\n if (open < 0) return null;\n let depth = 0;\n for (let i = open; i < src.length; i++) {\n const c = src[i];\n if (c === '{') depth++;\n else if (c === '}') {\n depth--;\n if (depth === 0) return src.slice(open + 1, i);\n }\n }\n return null;\n}\n\n/** Yield each `<name>: { ... }` group body inside a `variants` block. */\nfunction* extractGroupBodies(block: string): Generator<string> {\n const re = /(\\w+)\\s*:\\s*\\{/g;\n let m: RegExpExecArray | null;\n while ((m = re.exec(block)) !== null) {\n const open = block.indexOf('{', m.index);\n if (open < 0) continue;\n let depth = 0;\n for (let i = open; i < block.length; i++) {\n const c = block[i];\n if (c === '{') depth++;\n else if (c === '}') {\n depth--;\n if (depth === 0) {\n yield block.slice(open + 1, i);\n re.lastIndex = i + 1;\n break;\n }\n }\n }\n }\n}\n\nfunction setDiff(a: string[], b: string[]): string[] {\n const bset = new Set(b);\n return a.filter((x) => !bset.has(x)).sort();\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nfunction collectResourcesByEntry(\n resources: InstalledResource[],\n): Map<string, InstalledResource> {\n const out = new Map<string, InstalledResource>();\n for (const r of resources) {\n const colon = r.id.indexOf(':');\n const eid = colon >= 0 ? r.id.slice(0, colon) : r.id;\n if (!out.has(eid)) out.set(eid, r);\n }\n return out;\n}\n\nfunction aggregateByRisk(\n entries: UpgradeStagingEntry[],\n): Partial<Record<UpgradeRiskLevel, number>> {\n const out: Partial<Record<UpgradeRiskLevel, number>> = {};\n for (const e of entries) {\n const k = e.diff.riskLevel;\n out[k] = (out[k] ?? 0) + 1;\n }\n return out;\n}\n\n// ─── Promotion-vector heuristics (Init landing plan Phase 2.C.2) ────────────\n\ninterface DerivePromotionArgs {\n currentSource: string;\n incomingSource: string;\n targetName: string;\n}\n\n/**\n * Build the optional promotion-planning payload for a registered staging entry.\n *\n * The CLI emits this best-effort vector so the `promote-to-biz` skill can\n * recommend a default mode without re-deriving every axis. All axes use\n * regex-level heuristics — the skill is expected to refine via AST when the\n * confidence is below the threshold.\n */\nfunction derivePromotion(args: DerivePromotionArgs): UpgradeStagingPromotion {\n const fileType = classifyPromoteFileType(args.targetName, args.currentSource);\n const featureVector = buildFeatureVector(\n args.currentSource,\n args.incomingSource,\n );\n const { recommendedModes, confidence, reasons } = scorePromotionModes(\n fileType,\n featureVector,\n );\n return { fileType, featureVector, recommendedModes, confidence, reasons };\n}\n\n/**\n * Heuristic file-type classifier for the user's installed file. Mirrors\n * `ui-adopt.ts#classifyFile` but lighter — the staging emitter operates on\n * registered entries that already passed `ui add`, so the bias is towards\n * `component`.\n */\nfunction classifyPromoteFileType(\n targetName: string,\n src: string,\n): PromoteFileType {\n if (targetName.endsWith('.d.ts')) return 'type';\n if (/^use-[a-z0-9-]+\\.tsx?$/i.test(targetName)) return 'hook';\n const hasJsx = /<[A-Za-z][^>]*?>/.test(src);\n const hasReactImport = /from ['\"]react['\"]/.test(src);\n const hasProvider =\n /\\.Provider\\b/.test(src) || /createContext\\s*[<(]/.test(src);\n if (hasProvider && (hasJsx || hasReactImport)) return 'provider';\n if (hasJsx || /forwardRef\\s*[<(]/.test(src)) return 'component';\n if (!hasJsx && !hasReactImport) return 'util';\n return 'component';\n}\n\nfunction buildFeatureVector(\n current: string,\n incoming: string,\n): PromoteFeatureVector {\n const curExports = extractExportNames(current);\n const newExports = extractExportNames(incoming);\n // Promotion-vector perspective: \"added\" = user-side has it, upstream\n // does not (i.e. user added on top of upstream); \"removed\" = upstream\n // brings it but user has dropped it. Mirror inverse of classifyRisk above.\n const apiAdded = setDiff(curExports, newExports);\n const apiRemoved = setDiff(newExports, curExports);\n\n const curVariants = extractCvaVariantValues(current);\n const newVariants = extractCvaVariantValues(incoming);\n const cvaAdded = setDiff(curVariants, newVariants);\n const cvaModified: string[] = [];\n // \"modified\" — same key on both sides but body changed; we do a regex-level\n // proxy: a variant whose group body differs between current and incoming.\n const sharedVariants = curVariants.filter((v) => newVariants.includes(v));\n for (const v of sharedVariants) {\n if (extractVariantBody(current, v) !== extractVariantBody(incoming, v)) {\n cvaModified.push(v);\n }\n }\n\n // Style delta: heuristic on className literals & token references in current\n // (the user's file) compared to incoming.\n const curClass = extractClassNameLiterals(current);\n const newClass = extractClassNameLiterals(incoming);\n const classNameDiff = curClass !== newClass;\n const curTokens = extractTokenRefs(current);\n const newTokens = extractTokenRefs(incoming);\n const tokenUsageDiff =\n curTokens.size !== newTokens.size ||\n [...curTokens].some((t) => !newTokens.has(t));\n\n // Logic delta is read off the *current* (user) side — these signals decide\n // whether the user added stateful behaviour on top of the upstream import.\n const hasState = /\\buseState\\s*[<(]/.test(current);\n const hasEffect =\n /\\b(useEffect|useLayoutEffect|useMemo|useCallback)\\s*[<(]/.test(current);\n const curImports = extractImportSources(current);\n const newImports = extractImportSources(incoming);\n const hasExtraImports = [...curImports].some((src) => !newImports.has(src));\n\n // Structure delta — detect a composition pattern (multiple atomic children\n // rendered side-by-side) on the user side. Best effort: count distinct\n // capitalised JSX tag names; >2 distinct upstream-looking tags hints at a\n // compose pattern.\n const tagSet = new Set<string>();\n for (const m of current.matchAll(/<([A-Z]\\w+)[\\s/>]/g)) {\n if (m[1]) tagSet.add(m[1]);\n }\n const atomicChildren = [...tagSet];\n const isComposition = atomicChildren.length > 2;\n\n // Signature change — heuristic on default-export function parameter list.\n const signatureChanged =\n extractDefaultParamList(current) !== extractDefaultParamList(incoming);\n\n return {\n apiDelta: { added: apiAdded, removed: apiRemoved, signatureChanged },\n styleDelta: { classNameDiff, tokenUsageDiff },\n logicDelta: { hasState, hasEffect, hasExtraImports },\n cvaDelta: { addedVariants: cvaAdded, modifiedVariants: cvaModified },\n structureDelta: { isComposition, atomicChildren },\n };\n}\n\n/**\n * Score every mode independently, then return the recommended subset per the\n * Init landing plan §1.3 §5 (mode synthesis). Mutually exclusive terminals\n * (Coexist / Fork / TokenOnly) win when they fire; otherwise we return the\n * union of {Preset, Wrapper, Variant} above the 0.6 threshold.\n */\nfunction scorePromotionModes(\n fileType: PromoteFileType,\n fv: PromoteFeatureVector,\n): { recommendedModes: PromoteMode[]; confidence: number; reasons: string[] } {\n const reasons: string[] = [];\n if (fileType === 'hook' || fileType === 'util' || fileType === 'type') {\n reasons.push(\n `fileType=${fileType} — not a component, deferred to ManualReview`,\n );\n return { recommendedModes: ['ManualReview'], confidence: 0.5, reasons };\n }\n\n const apiNoChange =\n fv.apiDelta.added.length === 0 &&\n fv.apiDelta.removed.length === 0 &&\n !fv.apiDelta.signatureChanged;\n const logicMinimal =\n !fv.logicDelta.hasState &&\n !fv.logicDelta.hasEffect &&\n !fv.logicDelta.hasExtraImports;\n\n // Terminal modes (mutually exclusive)\n if (fv.apiDelta.removed.length > 0 || fv.apiDelta.signatureChanged) {\n reasons.push(\n 'signature changed or props removed — Coexist preserves user version',\n );\n return { recommendedModes: ['Coexist'], confidence: 0.85, reasons };\n }\n if (\n apiNoChange &&\n logicMinimal &&\n (fv.styleDelta.classNameDiff || fv.styleDelta.tokenUsageDiff) &&\n fv.cvaDelta.addedVariants.length === 0 &&\n fv.cvaDelta.modifiedVariants.length === 0\n ) {\n reasons.push(\n 'only style / token differences — push to tokens.overrides.css',\n );\n return { recommendedModes: ['TokenOnly'], confidence: 0.8, reasons };\n }\n\n const modes: PromoteMode[] = [];\n let score = 0;\n if (\n fv.cvaDelta.addedVariants.length > 0 ||\n fv.cvaDelta.modifiedVariants.length > 0\n ) {\n modes.push('Variant');\n reasons.push(\n `cva variants delta: +${fv.cvaDelta.addedVariants.length} ~${fv.cvaDelta.modifiedVariants.length}`,\n );\n score = Math.max(score, 0.7);\n }\n if (\n fv.logicDelta.hasState ||\n fv.logicDelta.hasEffect ||\n fv.logicDelta.hasExtraImports ||\n fv.apiDelta.added.length > 0\n ) {\n modes.push('Wrapper');\n reasons.push('user added state / effect / imports / props');\n score = Math.max(score, 0.75);\n }\n if (\n apiNoChange &&\n logicMinimal &&\n !fv.styleDelta.classNameDiff &&\n !fv.styleDelta.tokenUsageDiff &&\n fv.cvaDelta.addedVariants.length === 0 &&\n fv.cvaDelta.modifiedVariants.length === 0\n ) {\n // No detectable delta beyond defaults — Preset is the safe choice.\n modes.push('Preset');\n reasons.push('no API/logic delta — Preset captures default-prop tweaks');\n score = Math.max(score, 0.6);\n }\n if (fv.structureDelta.isComposition) {\n modes.push('Compose');\n reasons.push(\n `composition of ${fv.structureDelta.atomicChildren.length} atomic children`,\n );\n score = Math.max(score, 0.65);\n }\n\n if (modes.length === 0) {\n reasons.push('no axis crossed the 0.6 threshold');\n return { recommendedModes: ['ManualReview'], confidence: 0.4, reasons };\n }\n return { recommendedModes: modes, confidence: score, reasons };\n}\n\nfunction extractVariantBody(src: string, key: string): string {\n const block = extractVariantsBlock(src);\n if (block === null) return '';\n const re = new RegExp(`(?:[\"\\']?${key}[\"\\']?)\\\\s*:\\\\s*\\\\{`);\n const idx = block.search(re);\n if (idx < 0) return '';\n const open = block.indexOf('{', idx);\n if (open < 0) return '';\n let depth = 0;\n for (let i = open; i < block.length; i++) {\n const c = block[i];\n if (c === '{') depth++;\n else if (c === '}') {\n depth--;\n if (depth === 0) return block.slice(open + 1, i);\n }\n }\n return '';\n}\n\nfunction extractClassNameLiterals(src: string): string {\n const out: string[] = [];\n // 1) Static `className=\"...\"` / `className='...'` / `className={`...`}`.\n for (const m of src.matchAll(/className\\s*=\\s*[\"'`]([^\"'`]*)[\"'`]/g)) {\n if (m[1]) out.push(m[1]);\n }\n // 2) Dynamic `cn(...)` / `clsx(...)` / `cva(...)` calls — extract any\n // string literal arguments. shadcn-style components use these heavily,\n // so missing them under-counted classNameDiff signal (Concern-7).\n // We use a conservative approach: capture the call arglist, then pluck\n // out top-level string literals.\n for (const m of src.matchAll(/\\b(?:cn|clsx|cva)\\s*\\(/g)) {\n const open = (m.index ?? 0) + m[0].length - 1;\n let depth = 1;\n let i = open + 1;\n for (; i < src.length && depth > 0; i++) {\n const c = src[i];\n if (c === '(') depth++;\n else if (c === ')') depth--;\n }\n const body = src.slice(open + 1, i - 1);\n for (const lit of body.matchAll(/[\"'`]([^\"'`]*)[\"'`]/g)) {\n if (lit[1]) out.push(lit[1]);\n }\n }\n return out.sort().join('|');\n}\n\nfunction extractTokenRefs(src: string): Set<string> {\n const out = new Set<string>();\n for (const m of src.matchAll(/var\\(--([a-z0-9-]+)\\)/g)) {\n if (m[1]) out.add(m[1]);\n }\n for (const m of src.matchAll(/--([a-z][a-z0-9-]*)\\s*:/g)) {\n if (m[1]) out.add(m[1]);\n }\n return out;\n}\n\nfunction extractImportSources(src: string): Set<string> {\n const out = new Set<string>();\n for (const m of src.matchAll(/^\\s*import\\b[^'\"]*['\"]([^'\"]+)['\"]/gm)) {\n if (m[1]) out.add(m[1]);\n }\n return out;\n}\n\nfunction extractDefaultParamList(src: string): string {\n const m =\n /export\\s+default\\s+(?:async\\s+)?function\\s+\\w*\\s*\\(([^)]*)\\)/.exec(src) ??\n /export\\s+default\\s+(?:\\([^)]*\\)|\\w+)\\s*=>/.exec(src) ??\n /(?:const|function)\\s+\\w+\\s*=?\\s*(?:\\(([^)]*)\\)|\\w+)\\s*(?:=>|\\{)/.exec(src);\n return m?.[1]?.replace(/\\s+/g, ' ').trim() ?? '';\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport type {\n VariantManifest,\n Resource,\n InstalledResource,\n} from '@teamix-evo/registry';\nimport { writeFileSafe, ensureDir } from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport { renderTemplate, loadTemplateFile } from '../utils/template.js';\nimport { logger } from '../utils/logger.js';\nimport { resolveSourcePath, walkDir } from '../utils/path.js';\n\nexport interface InstallOptions {\n /** Project root directory */\n projectRoot: string;\n /** The variant manifest */\n manifest: VariantManifest;\n /** Template data for Handlebars rendering */\n data: Record<string, unknown>;\n /** Absolute path to the variant directory (where source files live) */\n variantDir: string;\n /** Absolute path to the package root (for resolving _template/ sources) */\n packageRoot: string;\n}\n\nexport interface InstallResult {\n /** Successfully installed resource records */\n resources: InstalledResource[];\n /** Number of resources installed */\n count: number;\n}\n\n/**\n * Install resources from a variant manifest into the project.\n */\nexport async function installResources(\n options: InstallOptions,\n): Promise<InstallResult> {\n const { projectRoot, manifest, data, variantDir, packageRoot } = options;\n const installedResources: InstalledResource[] = [];\n\n for (const resource of manifest.resources) {\n logger.debug(`Installing resource: ${resource.id} → ${resource.target}`);\n\n if (resource.recursive) {\n const results = await installRecursiveResource(\n resource,\n projectRoot,\n data,\n variantDir,\n packageRoot,\n );\n installedResources.push(...results);\n } else {\n const result = await installSingleResource(\n resource,\n projectRoot,\n data,\n variantDir,\n packageRoot,\n );\n installedResources.push(result);\n }\n }\n\n return {\n resources: installedResources,\n count: installedResources.length,\n };\n}\n\n/**\n * Install a single (non-recursive) resource.\n */\nasync function installSingleResource(\n resource: Resource,\n projectRoot: string,\n data: Record<string, unknown>,\n variantDir: string,\n packageRoot: string,\n): Promise<InstalledResource> {\n const sourcePath = resolveSourcePath(\n resource.source,\n variantDir,\n packageRoot,\n );\n const targetPath = path.join(projectRoot, resource.target);\n\n let content: string;\n if (resource.template) {\n const templateContent = await loadTemplateFile(sourcePath);\n content = renderTemplate(templateContent, data);\n } else {\n content = await fs.readFile(sourcePath, 'utf-8');\n }\n\n await writeFileSafe(targetPath, content);\n const hash = computeHash(content);\n\n logger.debug(` Written: ${resource.target} (${resource.updateStrategy})`);\n\n return {\n id: resource.id,\n target: resource.target,\n hash,\n strategy: resource.updateStrategy,\n };\n}\n\n/**\n * Install a recursive resource (directory).\n */\nasync function installRecursiveResource(\n resource: Resource,\n projectRoot: string,\n data: Record<string, unknown>,\n variantDir: string,\n packageRoot: string,\n): Promise<InstalledResource[]> {\n const sourcePath = resolveSourcePath(\n resource.source,\n variantDir,\n packageRoot,\n );\n const targetDir = path.join(projectRoot, resource.target);\n const results: InstalledResource[] = [];\n\n await ensureDir(targetDir);\n\n const entries = await walkDir(sourcePath);\n for (const entry of entries) {\n const relPath = path.relative(sourcePath, entry);\n let targetFile = path.join(targetDir, relPath);\n\n // Strip .hbs extension from target if template\n if (resource.template && targetFile.endsWith('.hbs')) {\n targetFile = targetFile.slice(0, -4);\n }\n\n let content: string;\n if (resource.template && entry.endsWith('.hbs')) {\n const templateContent = await loadTemplateFile(entry);\n content = renderTemplate(templateContent, data);\n } else {\n content = await fs.readFile(entry, 'utf-8');\n }\n\n await writeFileSafe(targetFile, content);\n const hash = computeHash(content);\n const targetRel = path.relative(projectRoot, targetFile);\n\n results.push({\n id: `${resource.id}:${relPath}`,\n target: targetRel,\n hash,\n strategy: resource.updateStrategy,\n });\n\n logger.debug(` Written: ${targetRel}`);\n }\n\n return results;\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport type { VariantManifest } from '@teamix-evo/registry';\nimport { loadVariantManifest } from '@teamix-evo/registry';\nimport { logger } from '../utils/logger.js';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Resolve the package root directory for a design package.\n */\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\n/**\n * Resolve the directory path for a variant inside a package.\n * MVP: resolves from local node_modules using require.resolve.\n *\n * @param packageName - e.g. \"@teamix-evo/tokens\"\n * @param variant - e.g. \"opentrek\"\n * @returns Absolute path to the variant directory (library/<variant>/)\n */\nexport function resolveVariantPackage(\n packageName: string,\n variant: string,\n): string {\n const pkgRoot = resolvePackageRoot(packageName);\n return path.join(pkgRoot, 'library', variant);\n}\n\n/**\n * Load the variant manifest and _data.json for template rendering.\n *\n * @param packageName - e.g. \"@teamix-evo/tokens\"\n * @param variant - e.g. \"opentrek\"\n * @returns manifest and data for template rendering\n */\nexport async function loadVariantData(\n packageName: string,\n variant: string,\n): Promise<{\n manifest: VariantManifest;\n data: Record<string, unknown>;\n variantDir: string;\n packageRoot: string;\n}> {\n const packageRoot = resolvePackageRoot(packageName);\n const variantDir = path.join(packageRoot, 'library', variant);\n\n logger.debug(`Resolved variant dir: ${variantDir}`);\n logger.debug(`Package root: ${packageRoot}`);\n\n // Load manifest\n const manifest = await loadVariantManifest(variantDir);\n\n // Load _data.json\n let data: Record<string, unknown> = {};\n const dataPath = path.join(variantDir, '_data.json');\n try {\n const raw = await fs.readFile(dataPath, 'utf-8');\n data = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err;\n }\n logger.debug(`No _data.json found at ${dataPath}, using empty data`);\n }\n\n return { manifest, data, variantDir, packageRoot };\n}\n"],"mappings":"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","names":["path","fs","rel","path","path","fs","require","path","fs","path","os","path","fs","path","fs","createRequire","require","stat","rel","targetFile","newContent","exists","written","path","DEFAULT_SKILLS_PACKAGE","DEFAULT_SKILLS_PACKAGE","FLAT_VARIANT","entry","path","fs","createRequire","require","createRequire","resolvePackageRoot","path","fs","DEFAULT_UI_PACKAGE","path","createRequire","loadUiPackageManifest","require","createRequire","resolvePackageRoot","loadUiPackageManifest","mergeResources","path","fs","rel","fs","path","hasManagedRegion","replaceManagedRegion","hasManagedRegion","replaceManagedRegion","fs","path","fs","path","stat","rel","path","fs","CONSUMER_TOKENS_DIR","CONSUMER_OVERRIDES_FILE","EMPTY_OVERRIDES_TEMPLATE","fs","path","TEAMIX_DIR","stat","fs","path","rel","rel","path","loadTokensPackageManifest","getVariantEntry","path","fs","loadTokensPackageManifest","getVariantEntry","path","TEAMIX_DIR","isoToFsSafe","compareSemver","hasManagedRegion","replaceManagedRegion","DEFAULT_TOKENS_PACKAGE","DEFAULT_TOKENS_PACKAGE","loadTokensPackageManifest","getVariantEntry","fs","path","stat","path","createRequire","loadUiPackageManifest","loadVariantUiPackageManifest","path","TEAMIX_DIR","PACKAGE_NAME","isoToFsSafe","createRequire","resolvePackageRoot","resolvePackageRoot","loadUiPackageManifest","loadVariantUiPackageManifest","DEFAULT_TOKENS_PACKAGE","DEFAULT_SKILLS_PACKAGE","CRITICAL_STEPS","loadTokensPackageManifest","getVariantEntry","path","fs","path","fs","createRequire","require","createRequire","resolvePackageRoot","resolvePackageRoot"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/tokens-init.ts","../../src/utils/fs.ts","../../src/utils/logger.ts","../../src/utils/hash.ts","../../src/core/state.ts","../../src/utils/error.ts","../../src/core/skills-client.ts","../../src/core/skills-installer.ts","../../src/ide/QoderAdapter.ts","../../src/ide/ClaudeAdapter.ts","../../src/ide/index.ts","../../src/utils/template.ts","../../src/utils/path.ts","../../src/utils/mcp.ts","../../src/core/skills-add.ts","../../src/core/skills-update.ts","../../src/core/ui-init.ts","../../src/core/ui-client.ts","../../src/core/ui-installer.ts","../../src/utils/transform-imports.ts","../../src/core/ui-add.ts","../../src/core/ui-list.ts","../../src/core/variant-ui-add.ts","../../src/core/lint-init.ts","../../src/core/agents-md.ts","../../src/core/init-detect.ts","../../src/core/init-conflicts.ts","../../src/core/deps-install.ts","../../src/core/init-checklist-template.ts","../../src/core/file-changes.ts","../../src/core/project-init.ts","../../src/core/installer.ts","../../src/core/registry-client.ts"],"sourcesContent":["/**\n * Programmatic tokens init — installs one variant's token files into the\n * consumer's project root `tokens/` directory.\n *\n * Per [ADR 0020](../../../../docs/adr/0020-design-to-tokens-skill-fusion.md)\n * the install model is now a flat copy: each variant in `@teamix-evo/tokens`\n * advertises its files in the package manifest; for each advertised file we\n * copy by basename into `<projectRoot>/tokens/`:\n *\n * variants/<variant>/theme.css → tokens/tokens.theme.css (regenerable)\n * variants/<variant>/base.tokens.json → (kept in package only — reference data)\n *\n * Plus we always ensure `tokens/tokens.overrides.css` exists at the consumer\n * (created empty if absent, frozen thereafter so user edits are preserved\n * across re-installs).\n *\n * No walk-and-merge, no `default` baseline — every variant is a\n * self-contained token set per ADR 0020 §3.\n */\nimport * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport {\n loadTokensPackageManifest,\n getVariantEntry,\n type TokensPackLock,\n type InstalledManifest,\n type InstalledResource,\n type ProjectConfig,\n type UpdateStrategy,\n} from '@teamix-evo/registry';\nimport { backupFile, writeFileSafe, fileExists } from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport {\n ensureTeamixDir,\n readProjectConfig,\n writeProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\nimport { runSkillsAdd } from './skills-add.js';\nimport { ensureMcpJson } from '../utils/mcp.js';\nimport { loadSkillsData } from './skills-client.js';\nimport { logger } from '../utils/logger.js';\nimport type { SkillIde, SkillScope } from '@teamix-evo/registry';\nimport { resolveTokensPackageRoot } from '../utils/path.js';\nimport { getErrorMessage } from '../utils/error.js';\n\nconst DEFAULT_SKILLS_PACKAGE = '@teamix-evo/skills';\nconst DEFAULT_AUTO_SKILL_IDES: SkillIde[] = ['qoder', 'claude'];\nconst DEFAULT_AUTO_SKILL_SCOPE: SkillScope = 'project';\n\nconst DEFAULT_TOKENS_PACKAGE = '@teamix-evo/tokens';\n\n/** Consumer-side directory where token files land. */\nconst CONSUMER_TOKENS_DIR = 'tokens';\n\n/** Consumer-side filename for the regenerable theme. */\nconst CONSUMER_THEME_FILE = 'tokens.theme.css';\n\n/** Consumer-side filename for the frozen user-owned override. */\nconst CONSUMER_OVERRIDES_FILE = 'tokens.overrides.css';\n\n/** Default empty content for a fresh `tokens.overrides.css`. */\nconst EMPTY_OVERRIDES_TEMPLATE = `/* User-owned token overrides — frozen on subsequent installs. */\n/* See @teamix-evo/tokens variant theme.css for available CSS custom properties. */\n`;\n\nexport interface RunTokensInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Tokens variant id (e.g. `\"opentrek\"`, `\"uni-manager\"`). */\n variant: string;\n /** IDE identifier written into config.json (e.g. `\"qoder\"`, `\"claude\"`). */\n ide: string;\n /** Override the tokens package name (defaults to `\"@teamix-evo/tokens\"`). */\n packageName?: string;\n /**\n * Override resolution of the tokens package root. When provided, skips\n * `require.resolve(\"<packageName>/package.json\")`. Useful for tests that\n * want to point at a fixture tree, and for embedding inside `create`\n * where the package may not yet be installed in the consumer.\n */\n packageRoot?: string;\n}\n\n/**\n * Outcome of the post-init skill auto-install step. `attempted` is the variant\n * skill id we tried to install; `addedSkillIds` is what was actually installed\n * (empty if the skill was already present); `missing` lists ids that aren't in\n * the manifest (warned, not fatal). Per ADR / \"skills self-contained\" decision,\n * each variant skill is fully self-contained — no separate baseline skill.\n */\nexport interface SkillsAutoInstallResult {\n attempted: string[];\n addedSkillIds: string[];\n skippedSkillIds: string[];\n missing: string[];\n}\n\nexport type RunTokensInitResult =\n | {\n status: 'installed';\n packageName: string;\n variant: string;\n version: string;\n count: number;\n resources: InstalledResource[];\n /** Result of the auto-install of the matching design skill. */\n skills?: SkillsAutoInstallResult;\n }\n | {\n status: 'already-initialized';\n existingVariant: string;\n }\n | {\n status: 'variant-mismatch';\n existingVariant: string;\n requestedVariant: string;\n };\n\n/**\n * Programmatic equivalent of `teamix-evo tokens init <variant>`.\n *\n * Side effects:\n * - Creates `<projectRoot>/.teamix-evo/`\n * - Copies the variant's `theme.css` to `<projectRoot>/tokens/tokens.theme.css`\n * - Ensures `<projectRoot>/tokens/tokens.overrides.css` exists (frozen)\n * - Writes `tokens-lock.json`, `config.json`, `manifest.json` (installed)\n *\n * No interactive prompts, no `process.exit`. Throws on hard failure (P8).\n */\nexport async function runTokensInit(\n options: RunTokensInitOptions,\n): Promise<RunTokensInitResult> {\n const { projectRoot, variant, ide } = options;\n const packageName = options.packageName ?? DEFAULT_TOKENS_PACKAGE;\n\n await ensureTeamixDir(projectRoot);\n\n // Resolve the catalog up front so variant-name validation runs before any\n // state-driven branching (#P2-3). An unknown variant should produce a\n // clear \"Unknown variant\" error regardless of whether tokens are already\n // installed for the project.\n const packageRoot =\n options.packageRoot ?? resolveTokensPackageRoot(packageName);\n const catalog = await loadTokensPackageManifest(packageRoot);\n const variantEntry = getVariantEntry(catalog, variant);\n if (!variantEntry) {\n const known = catalog.variants.map((v) => v.name).join(', ');\n throw new Error(\n `Unknown variant \"${variant}\". Available variants: ${\n known || '(none)'\n }.\\nRun \\`npx teamix-evo@latest tokens list-variants\\` to see all options.`,\n );\n }\n\n // Variant-switching guard: if a different variant is already installed,\n // require the user to explicitly uninstall first (#15). Same-variant re-init\n // is a no-op (already-initialized).\n const existingConfig = await readProjectConfig(projectRoot);\n if (existingConfig?.packages?.tokens) {\n const existingVariant = existingConfig.packages.tokens.variant;\n if (existingVariant === variant) {\n return { status: 'already-initialized', existingVariant };\n }\n return {\n status: 'variant-mismatch',\n existingVariant,\n requestedVariant: variant,\n };\n }\n\n // Install advertised files by basename → consumer tokens/ directory.\n const installed: InstalledResource[] = [];\n for (const fileRel of variantEntry.files) {\n const result = await installVariantFile(fileRel, packageRoot, projectRoot);\n if (result) installed.push(result);\n }\n\n // Always ensure the user-owned overrides file exists (frozen).\n const overridesAbs = path.join(\n projectRoot,\n CONSUMER_TOKENS_DIR,\n CONSUMER_OVERRIDES_FILE,\n );\n if (!(await fileExists(overridesAbs))) {\n await writeFileSafe(overridesAbs, EMPTY_OVERRIDES_TEMPLATE);\n }\n // Dedup: only add overrides resource if installVariantFile didn't already\n // register it (happens when the variant ships an overrides.css file).\n const overridesId = `tokens:${CONSUMER_OVERRIDES_FILE}`;\n if (!installed.some((r) => r.id === overridesId)) {\n const overridesContent = await fs.readFile(overridesAbs, 'utf-8');\n installed.push({\n id: overridesId,\n target: path.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_OVERRIDES_FILE),\n hash: computeHash(overridesContent),\n strategy: 'frozen',\n });\n }\n\n // Write consumer-side state files.\n const lock: TokensPackLock = {\n schemaVersion: 1,\n variant: {\n name: variantEntry.name,\n displayName: variantEntry.displayName,\n version: variantEntry.version,\n from: packageName,\n },\n packageVersion: catalog.version,\n linked: variantEntry.linked,\n installedAt: new Date().toISOString(),\n };\n await writeFileSafe(\n path.join(projectRoot, '.teamix-evo', 'tokens-lock.json'),\n JSON.stringify(lock, null, 2) + '\\n',\n );\n\n // Merge into existing config so unrelated package entries (skills / ui)\n // aren't clobbered (#18).\n const config: ProjectConfig = {\n $schema: 'https://teamix-evo.dev/schema/config/v2.json',\n schemaVersion: 2,\n ide: existingConfig?.ide ?? ide,\n packages: {\n ...(existingConfig?.packages ?? {}),\n tokens: {\n variant,\n version: variantEntry.version,\n tailwind: 'v4',\n },\n },\n };\n await writeProjectConfig(projectRoot, config);\n\n // Merge into existing installed manifest so other packages (ui / biz-ui /\n // templates) recorded earlier are preserved.\n const prior = (await readInstalledManifest(projectRoot)) ?? {\n schemaVersion: 1 as const,\n installed: [],\n };\n const tokensIdx = prior.installed.findIndex((p) => p.package === packageName);\n const tokensEntry = {\n package: packageName,\n variant,\n version: variantEntry.version,\n installedAt: new Date().toISOString(),\n resources: installed,\n };\n if (tokensIdx >= 0) prior.installed[tokensIdx] = tokensEntry;\n else prior.installed.push(tokensEntry);\n await writeInstalledManifest(projectRoot, prior);\n\n // Ensure `.mcp.json` exists for incremental adopters (#BUG-103). Done\n // before the auto-skills install so even if the latter fails the MCP\n // wiring is in place.\n await ensureMcpJson(projectRoot);\n\n // After the lock + manifest are persisted, auto-install matching skills.\n // Failures here do NOT roll back the install — the skill layer is additive,\n // and the user can always re-run `skills init` (bulk) or `skills add <id>`\n // (incremental) manually.\n const skills = await tryAutoInstallVariantSkills({\n projectRoot,\n variant,\n ide,\n });\n\n return {\n status: 'installed',\n packageName,\n variant,\n version: variantEntry.version,\n count: installed.length,\n resources: installed,\n skills,\n };\n}\n\n/**\n * Auto-install the variant skill `teamix-evo-design-<variant>` (if present\n * in the skills manifest). Each variant skill is fully self-contained — no\n * separate baseline. A missing variant skill produces a warning, not a failure.\n */\nasync function tryAutoInstallVariantSkills(args: {\n projectRoot: string;\n variant: string;\n ide: string;\n}): Promise<SkillsAutoInstallResult> {\n const { projectRoot, variant, ide } = args;\n const variantSkillId = `teamix-evo-design-${variant}`;\n const desired = [variantSkillId];\n\n // Filter to skills actually present in the manifest. Anything missing\n // becomes a warning but is not fatal.\n let manifestSkillIds: Set<string>;\n try {\n const { manifest } = await loadSkillsData(DEFAULT_SKILLS_PACKAGE);\n manifestSkillIds = new Set(manifest.skills.map((s) => s.id));\n } catch (err) {\n logger.warn(\n `Skipping skills auto-install: could not load skills manifest (${getErrorMessage(\n err,\n )}).`,\n );\n return {\n attempted: [],\n addedSkillIds: [],\n skippedSkillIds: [],\n missing: desired,\n };\n }\n\n const present = desired.filter((id) => manifestSkillIds.has(id));\n const missing = desired.filter((id) => !manifestSkillIds.has(id));\n if (missing.length > 0) {\n logger.warn(\n `Skills auto-install: not found in manifest, skipping: ${missing.join(\n ', ',\n )}.`,\n );\n }\n if (present.length === 0) {\n return {\n attempted: desired,\n addedSkillIds: [],\n skippedSkillIds: [],\n missing,\n };\n }\n\n try {\n const result = await runSkillsAdd({\n projectRoot,\n names: present,\n ides: DEFAULT_AUTO_SKILL_IDES,\n scope: DEFAULT_AUTO_SKILL_SCOPE,\n ide,\n });\n if (result.status !== 'installed') {\n return {\n attempted: desired,\n addedSkillIds: [],\n skippedSkillIds: present,\n missing,\n };\n }\n return {\n attempted: desired,\n addedSkillIds: result.addedSkillIds,\n skippedSkillIds: result.skippedSkillIds,\n missing,\n };\n } catch (err) {\n logger.warn(\n `Skills auto-install failed (continuing): ${getErrorMessage(err)}`,\n );\n return {\n attempted: desired,\n addedSkillIds: [],\n skippedSkillIds: [],\n missing,\n };\n }\n}\n\n/**\n * Install one advertised variant file. Mapping by basename:\n *\n * theme.css → consumer `tokens/tokens.theme.css` (regenerable)\n * overrides.css → consumer `tokens/tokens.overrides.css` (frozen, see runTokensInit)\n * anything else → skipped (reference data — kept in npm package only)\n *\n * The `overrides.css` source file is rare today (variants don't ship one),\n * but the mapping is here so authors can opt in. The \"always-create\" path in\n * `runTokensInit` covers the normal case where no source override is present.\n */\nasync function installVariantFile(\n fileRelToPackage: string,\n packageRoot: string,\n projectRoot: string,\n): Promise<InstalledResource | null> {\n const sourceAbs = path.join(packageRoot, fileRelToPackage);\n const base = path.basename(fileRelToPackage);\n\n if (base === 'theme.css') {\n const targetRel = path.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_THEME_FILE);\n const targetAbs = path.join(projectRoot, targetRel);\n const content = await fs.readFile(sourceAbs, 'utf-8');\n // Phase 1.A2: theme.css is regenerable but users sometimes hand-edit it.\n // Stash any pre-existing copy under .teamix-evo/.backups/ before we\n // overwrite so a stale-state recovery is always possible.\n if (await fileExists(targetAbs)) {\n await backupFile(targetAbs, projectRoot);\n }\n await writeFileSafe(targetAbs, content);\n return {\n id: `tokens:${CONSUMER_THEME_FILE}`,\n target: targetRel,\n hash: computeHash(content),\n strategy: 'regenerable',\n };\n }\n\n if (base === 'overrides.css' || base === 'tokens.overrides.css') {\n const targetRel = path.posix.join(\n CONSUMER_TOKENS_DIR,\n CONSUMER_OVERRIDES_FILE,\n );\n const targetAbs = path.join(projectRoot, targetRel);\n if (await fileExists(targetAbs)) {\n // Frozen — leave the user's customization alone.\n const existing = await fs.readFile(targetAbs, 'utf-8');\n return {\n id: `tokens:${CONSUMER_OVERRIDES_FILE}`,\n target: targetRel,\n hash: computeHash(existing),\n strategy: 'frozen',\n };\n }\n const content = await fs.readFile(sourceAbs, 'utf-8');\n await writeFileSafe(targetAbs, content);\n return {\n id: `tokens:${CONSUMER_OVERRIDES_FILE}`,\n target: targetRel,\n hash: computeHash(content),\n strategy: 'frozen',\n };\n }\n\n // Reference data (e.g. base.tokens.json) — kept in the npm package only.\n return null;\n}\n\n/**\n * List all variants advertised by the top-level tokens catalog. Used by\n * `teamix-evo tokens list-variants`.\n */\nexport interface ListVariantsResult {\n packageName: string;\n packageVersion: string;\n variants: Array<{\n name: string;\n displayName: string;\n version: string;\n description?: string;\n linked?: { 'biz-ui'?: string; templates?: string };\n }>;\n}\n\nexport async function listTokenVariants(\n packageName: string = DEFAULT_TOKENS_PACKAGE,\n packageRoot?: string,\n): Promise<ListVariantsResult> {\n const root = packageRoot ?? resolveTokensPackageRoot(packageName);\n const catalog = await loadTokensPackageManifest(root);\n return {\n packageName,\n packageVersion: catalog.version,\n variants: catalog.variants.map((v) => ({\n name: v.name,\n displayName: v.displayName,\n version: v.version,\n description: v.description,\n linked: v.linked,\n })),\n };\n}\n\n// Re-export the strategy enum constituents so consumers don't have to import\n// from registry separately.\nexport type { UpdateStrategy };\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { logger } from \"./logger.js\";\n\n/**\n * Recursively create a directory (like mkdir -p).\n */\nexport async function ensureDir(dir: string): Promise<void> {\n await fs.mkdir(dir, { recursive: true });\n}\n\n/**\n * Atomic write: write to a .tmp file first, then rename.\n */\nexport async function writeFileSafe(\n filePath: string,\n content: string,\n): Promise<void> {\n const dir = path.dirname(filePath);\n await ensureDir(dir);\n const tmp = filePath + \".tmp\";\n await fs.writeFile(tmp, content, \"utf-8\");\n await fs.rename(tmp, filePath);\n}\n\n/**\n * Read a file or return null if it doesn't exist.\n */\nexport async function readFileOrNull(\n filePath: string,\n): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null;\n }\n throw err;\n }\n}\n\n/**\n * Create a backup of a file under `.teamix-evo/.backups/`.\n */\nexport async function backupFile(\n filePath: string,\n projectRoot: string,\n): Promise<void> {\n const content = await readFileOrNull(filePath);\n if (content === null) {\n logger.debug(`Skip backup: ${filePath} does not exist`);\n return;\n }\n\n const rel = path.relative(projectRoot, filePath);\n const timestamp = new Date().toISOString().replace(/[:.]/g, \"-\");\n const backupPath = path.join(\n projectRoot,\n \".teamix-evo\",\n \".backups\",\n `${rel}.${timestamp}.bak`,\n );\n\n await ensureDir(path.dirname(backupPath));\n await fs.writeFile(backupPath, content, \"utf-8\");\n logger.debug(`Backed up ${rel} → ${path.relative(projectRoot, backupPath)}`);\n}\n\n/**\n * Check whether a file exists.\n */\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n","import { red, yellow, cyan, green, gray } from \"kolorist\";\n\nconst isDebug = process.env.TEAMIX_DEBUG === \"1\";\n\nexport const logger = {\n info(msg: string): void {\n console.log(cyan(\"ℹ\"), msg);\n },\n\n warn(msg: string): void {\n console.warn(yellow(\"⚠\"), msg);\n },\n\n error(msg: string): void {\n console.error(red(\"✖\"), msg);\n },\n\n success(msg: string): void {\n console.log(green(\"✔\"), msg);\n },\n\n debug(msg: string): void {\n if (isDebug) {\n console.log(gray(\"⊡\"), gray(msg));\n }\n },\n};\n","import { createHash } from \"node:crypto\";\n\n/**\n * Compute a SHA-256 hash of the given content.\n * Returns a string in the format \"sha256:<hex>\".\n */\nexport function computeHash(content: string): string {\n const hash = createHash(\"sha256\").update(content, \"utf-8\").digest(\"hex\");\n return `sha256:${hash}`;\n}\n","import * as path from 'node:path';\nimport type {\n ProjectConfig,\n InstalledManifest,\n InstalledPackage,\n SkillsLock,\n TokensPackLock,\n} from '@teamix-evo/registry';\nimport {\n validateConfig,\n validateInstalled,\n validateSkillsLock,\n TokensPackLockSchema,\n} from '@teamix-evo/registry';\nimport { readFileOrNull, writeFileSafe, ensureDir } from '../utils/fs.js';\nimport { getErrorMessage } from '../utils/error.js';\nimport { logger } from '../utils/logger.js';\n\nconst TEAMIX_DIR = '.teamix-evo';\nconst CONFIG_FILE = 'config.json';\nconst MANIFEST_FILE = 'manifest.json';\nconst TOKENS_LOCK_FILE = 'tokens-lock.json';\n/**\n * Consumer-side directory under `.teamix-evo/` that holds the skill source\n * mirrors (per ADR 0013). Renamed from `skills` → `skills-source` in the Init\n * landing improvement plan to avoid name-clash with installed package roots\n * and IDE mirror buckets; legacy paths are migrated lazily via\n * `migrateLegacySkillsSourceDir` (see `skills-installer.ts`).\n */\nconst SKILLS_DIR = 'skills-source';\n/** Legacy directory name retained for one-shot migration detection. */\nexport const LEGACY_SKILLS_DIR = 'skills';\nconst SKILLS_LOCK_FILE = 'manifest.lock.json';\n\n/**\n * Get the .teamix-evo directory path for a project.\n */\nexport function getTeamixDir(projectRoot: string): string {\n return path.join(projectRoot, TEAMIX_DIR);\n}\n\n/**\n * Ensure the .teamix-evo directory exists.\n */\nexport async function ensureTeamixDir(projectRoot: string): Promise<string> {\n const dir = getTeamixDir(projectRoot);\n await ensureDir(dir);\n return dir;\n}\n\n/**\n * Read the project config from .teamix-evo/config.json.\n * Returns null if the file does not exist; THROWS on corrupted content\n * so callers don't silently clobber prior config (#32 #18).\n */\nexport async function readProjectConfig(\n projectRoot: string,\n): Promise<ProjectConfig | null> {\n const configPath = path.join(projectRoot, TEAMIX_DIR, CONFIG_FILE);\n const raw = await readFileOrNull(configPath);\n if (raw === null) return null;\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `Corrupted config.json (${getErrorMessage(err)}). ` +\n `Fix the JSON manually or remove the file to start fresh; refusing to clobber prior config.`,\n );\n }\n const result = validateConfig(data);\n if (!result.success) {\n throw new Error(\n `Invalid config.json schema: ${result.error}. ` +\n `Fix the file manually or remove it to start fresh.`,\n );\n }\n return result.data;\n}\n\n/**\n * Write the project config to .teamix-evo/config.json.\n */\nexport async function writeProjectConfig(\n projectRoot: string,\n config: ProjectConfig,\n): Promise<void> {\n const configPath = path.join(projectRoot, TEAMIX_DIR, CONFIG_FILE);\n await writeFileSafe(configPath, JSON.stringify(config, null, 2) + '\\n');\n logger.debug(`Wrote config → ${configPath}`);\n}\n\n/**\n * Read the installed manifest from .teamix-evo/manifest.json.\n * Returns null if the file does not exist; THROWS on corrupted content so\n * callers don't silently lose prior installs by treating broken JSON as\n * \"fresh install\" (#32 #18). Use `readInstalledManifestOrNull` for the\n * old lenient behavior.\n */\nexport async function readInstalledManifest(\n projectRoot: string,\n): Promise<InstalledManifest | null> {\n const manifestPath = path.join(projectRoot, TEAMIX_DIR, MANIFEST_FILE);\n const raw = await readFileOrNull(manifestPath);\n if (raw === null) return null;\n\n let data: unknown;\n try {\n data = JSON.parse(raw);\n } catch (err) {\n throw new Error(\n `Corrupted manifest.json (${getErrorMessage(err)}). ` +\n `Fix the JSON manually or remove the file to start fresh; refusing to clobber prior install records.`,\n );\n }\n const result = validateInstalled(data);\n if (!result.success) {\n throw new Error(\n `Invalid manifest.json schema: ${result.error}. ` +\n `Fix the file manually or remove it to start fresh.`,\n );\n }\n return result.data;\n}\n\n/**\n * Write the installed manifest to .teamix-evo/manifest.json.\n */\nexport async function writeInstalledManifest(\n projectRoot: string,\n manifest: InstalledManifest,\n): Promise<void> {\n const manifestPath = path.join(projectRoot, TEAMIX_DIR, MANIFEST_FILE);\n await writeFileSafe(manifestPath, JSON.stringify(manifest, null, 2) + '\\n');\n logger.debug(`Wrote manifest → ${manifestPath}`);\n}\n\n/**\n * Read .teamix-evo/tokens-lock.json. Returns null if missing or invalid.\n */\nexport async function readTokensLock(\n projectRoot: string,\n): Promise<TokensPackLock | null> {\n const lockPath = path.join(projectRoot, TEAMIX_DIR, TOKENS_LOCK_FILE);\n const raw = await readFileOrNull(lockPath);\n if (raw === null) return null;\n try {\n const parsed = TokensPackLockSchema.safeParse(JSON.parse(raw));\n if (!parsed.success) {\n logger.warn(`Invalid tokens-lock.json: ${parsed.error.message}`);\n return null;\n }\n return parsed.data;\n } catch (err) {\n logger.warn(`Failed to parse tokens-lock.json: ${getErrorMessage(err)}`);\n return null;\n }\n}\n\n/**\n * Convenience: read just the variant id from tokens-lock.json. Returns null\n * when no tokens variant has been installed.\n */\nexport async function readTokensVariant(\n projectRoot: string,\n): Promise<string | null> {\n const lock = await readTokensLock(projectRoot);\n return lock?.variant.name ?? null;\n}\n\n/**\n * Absolute path to the per-skill source directory (consumer-side source).\n * Per ADR 0013, this is the truth source from which IDE mirrors are produced.\n * Resolves under `<projectRoot>/.teamix-evo/skills-source/[<skillName>]`.\n */\nexport function getSkillsSourceDir(\n projectRoot: string,\n skillName?: string,\n): string {\n const base = path.join(projectRoot, TEAMIX_DIR, SKILLS_DIR);\n return skillName ? path.join(base, skillName) : base;\n}\n\n/**\n * Absolute path to the legacy `<projectRoot>/.teamix-evo/skills/` directory.\n * Used **only** by the lazy migration path; do not write into this location.\n */\nexport function getLegacySkillsSourceDir(projectRoot: string): string {\n return path.join(projectRoot, TEAMIX_DIR, LEGACY_SKILLS_DIR);\n}\n\n/**\n * Read .teamix-evo/skills/manifest.lock.json. Returns null if missing.\n */\nexport async function readSkillsLock(\n projectRoot: string,\n): Promise<SkillsLock | null> {\n const lockPath = path.join(\n projectRoot,\n TEAMIX_DIR,\n SKILLS_DIR,\n SKILLS_LOCK_FILE,\n );\n const raw = await readFileOrNull(lockPath);\n if (raw === null) return null;\n try {\n const data = JSON.parse(raw);\n const result = validateSkillsLock(data);\n if (!result.success) {\n logger.warn(`Invalid skills manifest.lock.json: ${result.error}`);\n return null;\n }\n return result.data;\n } catch (err) {\n logger.warn(\n `Failed to parse skills manifest.lock.json: ${getErrorMessage(err)}`,\n );\n return null;\n }\n}\n\n/**\n * Write .teamix-evo/skills/manifest.lock.json.\n */\nexport async function writeSkillsLock(\n projectRoot: string,\n lock: SkillsLock,\n): Promise<void> {\n const lockPath = path.join(\n projectRoot,\n TEAMIX_DIR,\n SKILLS_DIR,\n SKILLS_LOCK_FILE,\n );\n await writeFileSafe(lockPath, JSON.stringify(lock, null, 2) + '\\n');\n logger.debug(`Wrote skills lock → ${lockPath}`);\n}\n\n/**\n * Look up an installed package record by package name.\n *\n * The {@link InstalledManifest} schema does not enforce uniqueness on the\n * `package` key — variant switches re-append a new record rather than\n * mutating the old one. We therefore return the **last** match (chronological\n * latest) and `null` when no record exists.\n *\n * Shared helper consumed by both {@link ui-upgrade-detector} and\n * {@link ui-upgrade-staging} to keep the lookup semantics aligned.\n */\nexport function findInstalledPackage(\n installed: InstalledManifest | null,\n packageName: string,\n): InstalledPackage | null {\n if (!installed) return null;\n const matches = installed.installed.filter((p) => p.package === packageName);\n if (matches.length === 0) return null;\n return matches[matches.length - 1] ?? null;\n}\n","/**\n * Safely extract an error message from an unknown thrown value.\n *\n * JavaScript allows `throw \"string\"` / `throw 42` / `throw null` — using\n * `(err as Error).message` directly is unsafe. This normaliser covers all\n * runtime cases.\n */\nexport function getErrorMessage(err: unknown): string {\n if (err instanceof Error) return err.message;\n if (typeof err === 'string') return err;\n try {\n return JSON.stringify(err);\n } catch {\n return String(err);\n }\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport type { SkillsPackageManifest } from '@teamix-evo/registry';\nimport { loadSkillsPackageManifest } from '@teamix-evo/registry';\nimport { logger } from '../utils/logger.js';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Resolve the package root directory for the skills package.\n */\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\n/**\n * Load the skills package manifest and optional shared `_data.json`.\n *\n * @param packageName - e.g. \"@teamix-evo/skills\"\n */\nexport async function loadSkillsData(packageName: string): Promise<{\n manifest: SkillsPackageManifest;\n data: Record<string, unknown>;\n packageRoot: string;\n}> {\n const packageRoot = resolvePackageRoot(packageName);\n\n logger.debug(`Resolved skills package root: ${packageRoot}`);\n\n const manifest = await loadSkillsPackageManifest(packageRoot);\n\n let data: Record<string, unknown> = {};\n const dataPath = path.join(packageRoot, '_data.json');\n try {\n const raw = await fs.readFile(dataPath, 'utf-8');\n data = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err;\n }\n logger.debug(`No _data.json found at ${dataPath}, using empty data`);\n }\n\n return { manifest, data, packageRoot };\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport type {\n SkillEntry,\n SkillsPackageManifest,\n InstalledResource,\n SkillIde,\n SkillScope,\n} from '@teamix-evo/registry';\nimport {\n replaceManagedRegion,\n hasManagedRegion,\n extractFrontmatter,\n replaceFrontmatter,\n} from '@teamix-evo/registry';\nimport { getAdapter } from '../ide/index.js';\nimport {\n writeFileSafe,\n readFileOrNull,\n fileExists,\n ensureDir,\n backupFile,\n} from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport { renderTemplate, loadTemplateFile } from '../utils/template.js';\nimport { logger } from '../utils/logger.js';\nimport { getErrorMessage } from '../utils/error.js';\nimport { walkDir } from '../utils/path.js';\nimport {\n getSkillsSourceDir,\n getLegacySkillsSourceDir,\n LEGACY_SKILLS_DIR,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\n\n/**\n * Source-mirror skills installer (per ADR 0013).\n *\n * Two-stage flow:\n * 1. **writeSkillSources** — render upstream `<packageRoot>/<skill.source>` and\n * write to `<projectRoot>/.teamix-evo/skills-source/<id>/` (the consumer-side\n * source of truth, regenerable, in git).\n * 2. **syncSkillsToIdes** — pure byte-for-byte copy from source dir to each\n * requested IDE mirror path (`.qoder/skills/<id>/`, `.claude/skills/<id>/`).\n * Mirrors are 100% derived; not subject to managed-region preservation.\n *\n * `installSkills` orchestrates both. `updateSkills` re-renders the source with\n * managed-region preservation against the existing source (NOT the mirrors),\n * then re-syncs.\n */\n\nexport interface SkillInstallOptions {\n /** Project root directory */\n projectRoot: string;\n /** Skills package manifest */\n manifest: SkillsPackageManifest;\n /** Template data */\n data: Record<string, unknown>;\n /** Absolute skills package root */\n packageRoot: string;\n /** IDE kinds to install for (intersection with skill.ides is computed) */\n ides: readonly SkillIde[];\n /** Install scope */\n scope: SkillScope;\n /** Optional: limit to specific skill ids */\n onlyIds?: string[];\n}\n\nexport interface SkillInstallResult {\n resources: InstalledResource[];\n count: number;\n}\n\n/**\n * Install (or reinstall) all skills declared in the manifest using the\n * source-mirror flow. Returns InstalledResource records for both source files\n * and IDE mirror files.\n */\nexport async function installSkills(\n options: SkillInstallOptions,\n): Promise<SkillInstallResult> {\n // One-shot lazy migration: rename legacy `.teamix-evo/skills/` to\n // `.teamix-evo/skills-source/` and rewrite manifest target paths if needed.\n // Runs unconditionally on every install; the function short-circuits when\n // there is nothing to migrate.\n await migrateLegacySkillsSourceDir(options.projectRoot);\n\n const { manifest, ides, scope, onlyIds } = options;\n const installed: InstalledResource[] = [];\n\n const targets = manifest.skills.filter(\n (s) => !onlyIds || onlyIds.includes(s.id),\n );\n\n for (const skill of targets) {\n const skillIdes = skill.ides.filter((i) => ides.includes(i));\n if (skillIdes.length === 0) {\n logger.warn(\n `Skill \"${skill.name}\" supports [${skill.ides.join(\n ',',\n )}], no overlap with [${ides.join(',')}]; skipped.`,\n );\n continue;\n }\n\n const sourceRecords = await writeSkillSource(skill, options);\n installed.push(...sourceRecords);\n\n for (const ide of skillIdes) {\n const mirrorRecords = await mirrorSkillToIde(\n skill,\n ide,\n scope,\n options.projectRoot,\n );\n installed.push(...mirrorRecords);\n }\n }\n\n return { resources: installed, count: installed.length };\n}\n\n/**\n * Render upstream skill source(s) and write to `.teamix-evo/skills/<id>/`.\n * Returns InstalledResource records (one per file) describing the source files.\n */\nasync function writeSkillSource(\n skill: SkillEntry,\n options: SkillInstallOptions,\n): Promise<InstalledResource[]> {\n const { data, packageRoot, projectRoot } = options;\n const sourceAbs = path.resolve(packageRoot, skill.source);\n const targetDir = getSkillsSourceDir(projectRoot, skill.name);\n const stat = await fs.stat(sourceAbs);\n const records: InstalledResource[] = [];\n\n if (stat.isFile()) {\n const targetFile = path.join(targetDir, 'SKILL.md');\n const content = await renderSkillContent(sourceAbs, skill, data);\n await writeFileSafe(targetFile, content);\n records.push(makeSourceRecord(skill, targetFile, content));\n logger.debug(` Wrote source: ${targetFile}`);\n return records;\n }\n\n await ensureDir(targetDir);\n const entries = await walkDir(sourceAbs);\n for (const entry of entries) {\n const rel = path.relative(sourceAbs, entry);\n let targetFile = path.join(targetDir, rel);\n if (skill.template && targetFile.endsWith('.hbs')) {\n targetFile = targetFile.slice(0, -4);\n }\n const content =\n skill.template && entry.endsWith('.hbs')\n ? renderTemplate(await loadTemplateFile(entry), { ...data, skill })\n : await fs.readFile(entry, 'utf-8');\n await writeFileSafe(targetFile, content);\n const relWritten = path.relative(targetDir, targetFile);\n records.push(makeSourceRecord(skill, targetFile, content, relWritten));\n logger.debug(` Wrote source: ${targetFile}`);\n }\n return records;\n}\n\n/**\n * Mirror an installed skill source to a single IDE path.\n *\n * Per ADR 0013, mirrors are normally pure byte-for-byte copies of source.\n * However, when the existing mirror file already contains managed-region\n * markers that match the skill's declared `managedRegions`, the writer falls\n * back to a managed-region replacement (#BUG-101) so user-authored notes\n * outside the markers are preserved across `skills update` / `skills sync`.\n * If markers are absent, the full source content is written (backward-compat).\n */\nasync function mirrorSkillToIde(\n skill: SkillEntry,\n ide: SkillIde,\n scope: SkillScope,\n projectRoot: string,\n): Promise<InstalledResource[]> {\n const sourceDir = getSkillsSourceDir(projectRoot, skill.name);\n const adapter = getAdapter(ide);\n const targetDir = adapter.getSkillTargetDir(skill.name, scope, projectRoot);\n const records: InstalledResource[] = [];\n\n const sourceFiles = await walkDir(sourceDir);\n await ensureDir(targetDir);\n for (const src of sourceFiles) {\n const rel = path.relative(sourceDir, src);\n const targetFile = path.join(targetDir, rel);\n const sourceContent = await fs.readFile(src, 'utf-8');\n\n const writtenContent = await writeMirrorContent(\n targetFile,\n sourceContent,\n skill.managedRegions,\n src,\n );\n records.push(\n makeMirrorRecord(skill, targetFile, writtenContent, ide, scope, rel),\n );\n logger.debug(` Mirrored ${ide}:${scope}: ${targetFile}`);\n }\n return records;\n}\n\n/**\n * Write a mirror file with optional managed-region preservation (#BUG-101).\n *\n * Behavior:\n * - Target absent → full write of source.\n * - `managedRegions` empty/undefined OR existing mirror has no matching\n * markers → full overwrite (with drift warning if content differs).\n * - Otherwise → replace each present managed region's content from the\n * source into the existing mirror, preserving content outside markers.\n *\n * Returns the bytes actually written (used for the InstalledResource hash).\n */\nasync function writeMirrorContent(\n targetFile: string,\n sourceContent: string,\n managedRegions: readonly string[] | undefined,\n sourceFile: string,\n): Promise<string> {\n const existing = await readFileOrNull(targetFile);\n\n if (existing === null) {\n await writeFileSafe(targetFile, sourceContent);\n return sourceContent;\n }\n\n const regions = managedRegions ?? [];\n const matchedRegions = regions.filter((id) => hasManagedRegion(existing, id));\n\n if (matchedRegions.length === 0) {\n if (existing !== sourceContent) {\n logger.warn(\n `Mirror drift detected at ${targetFile} — overwriting from source. ` +\n `Edit ${sourceFile} (not the mirror) and re-run \\`npx teamix-evo@latest skills sync\\`.`,\n );\n await writeFileSafe(targetFile, sourceContent);\n return sourceContent;\n }\n return existing;\n }\n\n let merged = existing;\n // ADR 0015: frontmatter is the IDE-facing protocol — always pull from\n // upstream so trigger/description changes propagate through update + sync\n // without requiring uninstall + reinstall. Body outside managed regions\n // remains user-owned.\n const upstreamFm = extractFrontmatter(sourceContent);\n if (upstreamFm) {\n merged = replaceFrontmatter(merged, upstreamFm);\n }\n for (const id of matchedRegions) {\n const newRegion = extractRegionBody(sourceContent, id);\n if (newRegion === null) continue;\n try {\n merged = replaceManagedRegion(merged, id, newRegion);\n } catch {\n // Region present in existing but pattern failed; skip safely.\n }\n }\n if (merged !== existing) {\n await writeFileSafe(targetFile, merged);\n }\n return merged;\n}\n\nfunction extractRegionBody(content: string, id: string): string | null {\n const re = new RegExp(\n `<!-- teamix-evo:managed:start id=\"${escapeRegExp(\n id,\n )}\" -->([\\\\s\\\\S]*?)<!-- teamix-evo:managed:end id=\"${escapeRegExp(\n id,\n )}\" -->`,\n );\n const m = content.match(re);\n if (!m) return null;\n return m[1]!.replace(/^\\n/, '').replace(/\\n$/, '');\n}\n\nasync function renderSkillContent(\n sourceAbs: string,\n skill: SkillEntry,\n data: Record<string, unknown>,\n): Promise<string> {\n if (skill.template ?? sourceAbs.endsWith('.hbs')) {\n const tpl = await loadTemplateFile(sourceAbs);\n return renderTemplate(tpl, { ...data, skill });\n }\n return fs.readFile(sourceAbs, 'utf-8');\n}\n\nfunction makeSourceRecord(\n skill: SkillEntry,\n targetAbs: string,\n content: string,\n rel?: string,\n): InstalledResource {\n const id = rel ? `${skill.id}:source:${rel}` : `${skill.id}:source`;\n return {\n id,\n target: targetAbs,\n hash: computeHash(content),\n strategy: skill.updateStrategy,\n };\n}\n\nfunction makeMirrorRecord(\n skill: SkillEntry,\n targetAbs: string,\n content: string,\n ide: SkillIde,\n scope: SkillScope,\n rel?: string,\n): InstalledResource {\n const id = rel && rel !== 'SKILL.md' ? `${skill.id}:${rel}` : skill.id;\n return {\n id,\n target: targetAbs,\n hash: computeHash(content),\n strategy: skill.updateStrategy,\n ide,\n scope,\n };\n}\n\nexport interface SkillUpdateOptions extends SkillInstallOptions {\n /**\n * Optional: existing installed records (legacy parameter kept for callers that\n * still pass it). The refactored updater consults the file-system source under\n * `.teamix-evo/skills/<id>/` for managed-region preservation, so this is\n * unused by the new flow. Callers should stop passing it.\n */\n installed?: InstalledResource[];\n /**\n * Optional: limit the update to these skill ids. When provided, skills not\n * in the set are skipped (no source rewrite, no mirror). Per ADR 0035,\n * the high-level `runSkillsUpdate` always passes this with the intersection\n * of `keys(lock.skills)` and the current install scope, ensuring update\n * never accidentally installs new skills or skills from a mismatched scope.\n *\n * Type matches `SkillInstallOptions.onlyIds` (mutable `string[] | undefined`).\n */\n onlyIds?: string[];\n}\n\nexport interface SkillUpdateResult {\n resources: InstalledResource[];\n summary: {\n overwritten: number;\n managed: number;\n skipped: number;\n created: number;\n };\n}\n\n/**\n * Update skills with managed-region preservation applied at the SOURCE layer\n * (not the mirrors). After source is rewritten, mirrors are re-synced cleanly.\n */\nexport async function updateSkills(\n options: SkillUpdateOptions,\n): Promise<SkillUpdateResult> {\n const { manifest, ides, scope, projectRoot } = options;\n const idFilter = options.onlyIds ? new Set(options.onlyIds) : null;\n const summary = { overwritten: 0, managed: 0, skipped: 0, created: 0 };\n const updated: InstalledResource[] = [];\n\n for (const skill of manifest.skills) {\n if (idFilter && !idFilter.has(skill.id)) continue;\n const skillIdes = skill.ides.filter((i) => ides.includes(i));\n if (skillIdes.length === 0) continue;\n\n const sourceRecords = await rewriteSkillSource(skill, options, summary);\n updated.push(...sourceRecords);\n\n // Mirrors are always overwritten cleanly from the (now updated) source.\n for (const ide of skillIdes) {\n const mirrorRecords = await mirrorSkillToIde(\n skill,\n ide,\n scope,\n projectRoot,\n );\n updated.push(...mirrorRecords);\n }\n }\n\n return { resources: updated, summary };\n}\n\nasync function rewriteSkillSource(\n skill: SkillEntry,\n options: SkillUpdateOptions,\n summary: SkillUpdateResult['summary'],\n): Promise<InstalledResource[]> {\n const { data, packageRoot, projectRoot } = options;\n const sourceAbs = path.resolve(packageRoot, skill.source);\n const targetDir = getSkillsSourceDir(projectRoot, skill.name);\n const stat = await fs.stat(sourceAbs);\n\n if (!stat.isFile()) {\n await ensureDir(targetDir);\n const entries = await walkDir(sourceAbs);\n const records: InstalledResource[] = [];\n for (const entry of entries) {\n const rel = path.relative(sourceAbs, entry);\n let targetFile = path.join(targetDir, rel);\n if (skill.template && targetFile.endsWith('.hbs')) {\n targetFile = targetFile.slice(0, -4);\n }\n const newContent =\n skill.template && entry.endsWith('.hbs')\n ? renderTemplate(await loadTemplateFile(entry), { ...data, skill })\n : await fs.readFile(entry, 'utf-8');\n const exists = await fileExists(targetFile);\n\n const written = await rewriteSingleFile({\n targetFile,\n newContent,\n exists,\n updateStrategy: skill.updateStrategy,\n managedRegions: skill.managedRegions,\n projectRoot,\n summary,\n });\n const relWritten = path.relative(targetDir, targetFile);\n records.push(makeSourceRecord(skill, targetFile, written, relWritten));\n }\n return records;\n }\n\n // Single-file skill: target = .teamix-evo/skills/<id>/SKILL.md\n const targetFile = path.join(targetDir, 'SKILL.md');\n const newContent = await renderSkillContent(sourceAbs, skill, data);\n const exists = await fileExists(targetFile);\n\n const written = await rewriteSingleFile({\n targetFile,\n newContent,\n exists,\n updateStrategy: skill.updateStrategy,\n managedRegions: skill.managedRegions,\n projectRoot,\n summary,\n });\n return [makeSourceRecord(skill, targetFile, written)];\n}\n\n/**\n * Apply updateStrategy logic to a single file (used by both single-file and\n * directory skill update paths).\n *\n * Returns the content actually on disk after the operation.\n */\nasync function rewriteSingleFile(args: {\n targetFile: string;\n newContent: string;\n exists: boolean;\n updateStrategy: SkillEntry['updateStrategy'];\n managedRegions: readonly string[] | undefined;\n projectRoot: string;\n summary: SkillUpdateResult['summary'];\n}): Promise<string> {\n const {\n targetFile,\n newContent,\n exists,\n updateStrategy,\n managedRegions,\n projectRoot,\n summary,\n } = args;\n\n if (updateStrategy === 'frozen') {\n if (exists) {\n summary.skipped++;\n return (await readFileOrNull(targetFile)) ?? newContent;\n }\n await writeFileSafe(targetFile, newContent);\n summary.created++;\n return newContent;\n }\n\n if (updateStrategy === 'regenerable' || !exists) {\n if (exists) {\n await backupFile(targetFile, projectRoot);\n summary.overwritten++;\n } else {\n summary.created++;\n }\n await writeFileSafe(targetFile, newContent);\n return newContent;\n }\n\n // managed: preserve outside-region content from the existing SOURCE.\n // Per ADR 0015, the YAML frontmatter is part of the skill's PROTOCOL\n // (name / description / trigger contract) and MUST always follow the\n // upstream package — only the body outside managed regions is treated\n // as user-owned. We therefore overlay the upstream frontmatter first,\n // then apply managed-region replacement on the body.\n const current = await readFileOrNull(targetFile);\n let merged = current ?? newContent;\n const upstreamFm = extractFrontmatter(newContent);\n if (upstreamFm) {\n merged = replaceFrontmatter(merged, upstreamFm);\n }\n for (const regionId of managedRegions ?? []) {\n const re = new RegExp(\n `<!-- teamix-evo:managed:start id=\"${escapeRegExp(\n regionId,\n )}\" -->([\\\\s\\\\S]*?)<!-- teamix-evo:managed:end id=\"${escapeRegExp(\n regionId,\n )}\" -->`,\n );\n const match = newContent.match(re);\n if (match) {\n const region = match[1]!.replace(/^\\n/, '').replace(/\\n$/, '');\n try {\n merged = replaceManagedRegion(merged, regionId, region);\n } catch {\n logger.warn(\n `Managed region \"${regionId}\" not found in ${targetFile}. Skipped.`,\n );\n }\n }\n }\n if (merged !== current) {\n await backupFile(targetFile, projectRoot);\n await writeFileSafe(targetFile, merged);\n }\n summary.managed++;\n return merged;\n}\n\nfunction escapeRegExp(str: string): string {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\n/**\n * Sync existing skill sources to the requested IDE mirror paths.\n *\n * Used by:\n * - `skills add` (immediate mirror after source write — handled by installSkills)\n * - `skills sync` (re-mirror after the user adds an IDE or moves machines)\n * - `skills update` (re-mirror after source is rewritten)\n *\n * `onlyIds` lets the caller limit which skills are synced.\n */\nexport interface SkillSyncOptions {\n projectRoot: string;\n /** Skills present in the source dir to mirror (caller derives from lock). */\n skills: ReadonlyArray<{\n id: string;\n name: string;\n updateStrategy: SkillEntry['updateStrategy'];\n /** Managed-region ids for region-aware mirror sync. */\n managedRegions?: readonly string[];\n }>;\n ides: readonly SkillIde[];\n scope: SkillScope;\n onlyIds?: string[];\n}\n\nexport interface SkillSyncResult {\n resources: InstalledResource[];\n count: number;\n}\n\n/**\n * Mirror existing source dirs (`.teamix-evo/skills/<id>/`) to the given IDE\n * paths. Pure byte-for-byte copy — no rendering, no merge.\n */\nexport async function syncSkillsToIdes(\n options: SkillSyncOptions,\n): Promise<SkillSyncResult> {\n // One-shot lazy migration so a stale `.teamix-evo/skills/` from a prior CLI\n // version is moved to the new layout before we walk source dirs.\n await migrateLegacySkillsSourceDir(options.projectRoot);\n\n const { projectRoot, skills, ides, scope, onlyIds } = options;\n const out: InstalledResource[] = [];\n\n const targets = skills.filter((s) => !onlyIds || onlyIds.includes(s.id));\n for (const skill of targets) {\n const sourceDir = getSkillsSourceDir(projectRoot, skill.name);\n if (!(await fileExists(sourceDir))) {\n logger.warn(\n `Skill \"${skill.id}\" has no source at ${sourceDir}; skipped.`,\n );\n continue;\n }\n for (const ide of ides) {\n const adapter = getAdapter(ide);\n const targetDir = adapter.getSkillTargetDir(\n skill.name,\n scope,\n projectRoot,\n );\n await ensureDir(targetDir);\n const sourceFiles = await walkDir(sourceDir);\n for (const src of sourceFiles) {\n const rel = path.relative(sourceDir, src);\n const targetFile = path.join(targetDir, rel);\n const sourceContent = await fs.readFile(src, 'utf-8');\n\n // Region-aware mirror write (#BUG-101): keep user content outside\n // managed markers when the mirror already has them; otherwise full\n // overwrite (with drift warning).\n const writtenContent = await writeMirrorContent(\n targetFile,\n sourceContent,\n skill.managedRegions,\n src,\n );\n out.push({\n id: rel === 'SKILL.md' ? skill.id : `${skill.id}:${rel}`,\n target: targetFile,\n hash: computeHash(writtenContent),\n strategy: skill.updateStrategy,\n ide,\n scope,\n });\n }\n }\n }\n return { resources: out, count: out.length };\n}\n\n/**\n * One-shot migration of the consumer-side skill source directory from the\n * legacy `<projectRoot>/.teamix-evo/skills/` layout to the current\n * `<projectRoot>/.teamix-evo/skills-source/` layout (Init landing plan §A3).\n *\n * Behavior:\n * - When **only** the legacy dir exists → rename it to `skills-source`.\n * - When both exist → keep `skills-source` authoritative; warn that legacy\n * `skills/` is now stale (caller may delete manually).\n * - When neither exists or only `skills-source/` exists → no-op.\n *\n * Side effects:\n * - Updates `InstalledManifest` resources whose `target` still references the\n * legacy `.teamix-evo/skills/` path so subsequent `findInstalledPackage` /\n * uninstall lookups don't dangle.\n *\n * Failures are logged and swallowed: the rest of the install/sync should not\n * be blocked by a best-effort migration step.\n */\nexport async function migrateLegacySkillsSourceDir(\n projectRoot: string,\n): Promise<void> {\n const legacyDir = getLegacySkillsSourceDir(projectRoot);\n const newDir = getSkillsSourceDir(projectRoot);\n\n let legacyExists = false;\n let newExists = false;\n try {\n legacyExists = (await fs.stat(legacyDir)).isDirectory();\n } catch {\n legacyExists = false;\n }\n try {\n newExists = (await fs.stat(newDir)).isDirectory();\n } catch {\n newExists = false;\n }\n\n if (!legacyExists) return;\n if (newExists) {\n logger.warn(\n `Detected stale legacy skills source dir at ${legacyDir} alongside ${newDir}; ` +\n `the new layout takes precedence — you can safely delete the legacy dir.`,\n );\n return;\n }\n\n try {\n await fs.rename(legacyDir, newDir);\n logger.info(\n `Migrated skills source dir: \\`.teamix-evo/${LEGACY_SKILLS_DIR}/\\` → \\`.teamix-evo/skills-source/\\``,\n );\n } catch (err) {\n logger.warn(\n `Failed to rename legacy skills source dir (${getErrorMessage(\n err,\n )}); leaving as-is. New skills will install under the new layout.`,\n );\n return;\n }\n\n // Rewrite manifest targets that still reference the legacy path. We match\n // both POSIX and platform-native separators because Windows installs may\n // have stored back-slashed absolute paths.\n try {\n const manifest = await readInstalledManifest(projectRoot);\n if (!manifest) return;\n const legacyFragmentPosix = `/.teamix-evo/${LEGACY_SKILLS_DIR}/`;\n const newFragmentPosix = `/.teamix-evo/skills-source/`;\n const legacyFragmentNative = `${path.sep}.teamix-evo${path.sep}${LEGACY_SKILLS_DIR}${path.sep}`;\n const newFragmentNative = `${path.sep}.teamix-evo${path.sep}skills-source${path.sep}`;\n let touched = 0;\n for (const pkg of manifest.installed) {\n for (const r of pkg.resources) {\n if (typeof r.target !== 'string') continue;\n const before = r.target;\n let after = before.replace(legacyFragmentPosix, newFragmentPosix);\n after = after.replace(legacyFragmentNative, newFragmentNative);\n if (after !== before) {\n r.target = after;\n touched += 1;\n }\n }\n }\n if (touched > 0) {\n await writeInstalledManifest(projectRoot, manifest);\n logger.debug(\n `Rewrote ${touched} manifest target(s) to the new skills-source path.`,\n );\n }\n } catch (err) {\n logger.warn(\n `Migrated skills source dir but failed to update manifest paths (${getErrorMessage(\n err,\n )}); manifest may still reference legacy paths.`,\n );\n }\n}\n\n/**\n * Prune empty IDE skill directories under each adapter's skill root.\n *\n * Some workflows leave behind empty `<ide-root>/skills/<id>/` shells — e.g.\n * the upstream package dropped a skill, the user toggled it out via\n * `onlyIds`, or a partial mirror failed mid-write and removed the SKILL.md\n * but not the parent dir. Per the Init landing plan §G, every install /\n * sync run sweeps these out so the IDE side stays tidy.\n *\n * Safety:\n * - Only completely empty dirs are removed (no SKILL.md AND no other files).\n * - Non-empty dirs without SKILL.md are LEFT ALONE; deciding whether they\n * are user content vs stale mirror is out of scope for this best-effort\n * pass.\n * - All errors are swallowed; this is decoration, never a hard failure.\n *\n * Returns the list of absolute paths that were removed (for diagnostics).\n */\nexport async function pruneEmptyIdeSkillDirs(args: {\n projectRoot: string;\n ides: readonly SkillIde[];\n scope: SkillScope;\n}): Promise<string[]> {\n const removed: string[] = [];\n for (const ide of args.ides) {\n const adapter = getAdapter(ide);\n // Use a placeholder name to derive the per-IDE skill root, then take\n // dirname — every adapter returns `<root>/<name>/` shape.\n const placeholderDir = adapter.getSkillTargetDir(\n '__placeholder__',\n args.scope,\n args.projectRoot,\n );\n const skillsRoot = path.dirname(placeholderDir);\n let entries: string[];\n try {\n entries = await fs.readdir(skillsRoot);\n } catch {\n continue;\n }\n for (const name of entries) {\n const dir = path.join(skillsRoot, name);\n let stat;\n try {\n stat = await fs.stat(dir);\n } catch {\n continue;\n }\n if (!stat.isDirectory()) continue;\n let children: string[];\n try {\n children = await fs.readdir(dir);\n } catch {\n continue;\n }\n // Skip dirs that still contain a SKILL.md — they're live.\n if (children.some((c) => c === 'SKILL.md')) continue;\n // Only delete completely empty dirs; preserve any user content\n // sitting in a SKILL.md-less directory.\n if (children.length !== 0) continue;\n try {\n await fs.rmdir(dir);\n removed.push(dir);\n logger.debug(`Pruned empty IDE skill dir: ${dir}`);\n } catch {\n // Best-effort; ignore.\n }\n }\n }\n return removed;\n}\n\n/**\n * Remove all installed skill files. Returns the absolute paths removed.\n * After files are unlinked, walks up the directory tree pruning empty dirs\n * until a non-empty ancestor is reached (#33).\n */\nexport async function removeSkillFiles(\n records: InstalledResource[],\n): Promise<string[]> {\n const removed: string[] = [];\n for (const r of records) {\n try {\n await fs.unlink(r.target);\n removed.push(r.target);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n logger.warn(`Failed to remove ${r.target}: ${getErrorMessage(err)}`);\n }\n }\n }\n // Walk-up empty-dir prune. Collect immediate parents, then for each, walk\n // up the tree calling rmdir as long as the dir is empty. Bound the walk\n // to a small depth to prevent runaway in pathological filesystems.\n const startDirs = new Set(records.map((r) => path.dirname(r.target)));\n for (const startDir of startDirs) {\n let dir = startDir;\n for (let depth = 0; depth < 8; depth++) {\n try {\n const entries = await fs.readdir(dir);\n if (entries.length !== 0) break;\n await fs.rmdir(dir);\n } catch {\n break;\n }\n dir = path.dirname(dir);\n }\n }\n return removed;\n}\n","import * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { SkillScope } from '@teamix-evo/registry';\nimport type { IdeAdapter } from './IdeAdapter.js';\n\n/**\n * Qoder IDE adapter.\n * Skill paths:\n * - project: <projectRoot>/.qoder/skills/<name>/\n * - global: ~/.qoder/skills/<name>/\n */\nexport class QoderAdapter implements IdeAdapter {\n readonly kind = 'qoder' as const;\n readonly name = 'qoder';\n\n getProjectRoot(): string {\n return process.cwd();\n }\n\n detectIde(): boolean {\n // MVP: default to true. Future: check environment variables\n return true;\n }\n\n getSkillTargetDir(\n skillName: string,\n scope: SkillScope,\n projectRoot?: string,\n ): string {\n const base =\n scope === 'global'\n ? path.join(os.homedir(), '.qoder')\n : path.join(projectRoot ?? this.getProjectRoot(), '.qoder');\n return path.join(base, 'skills', skillName);\n }\n}\n","import * as os from 'node:os';\nimport * as path from 'node:path';\nimport type { SkillScope } from '@teamix-evo/registry';\nimport type { IdeAdapter } from './IdeAdapter.js';\n\n/**\n * Claude Code IDE adapter.\n * Skill paths:\n * - project: <projectRoot>/.claude/skills/<name>/\n * - global: ~/.claude/skills/<name>/\n */\nexport class ClaudeAdapter implements IdeAdapter {\n readonly kind = 'claude' as const;\n readonly name = 'claude';\n\n getProjectRoot(): string {\n return process.cwd();\n }\n\n detectIde(): boolean {\n // Best-effort: presence of .claude/ in cwd or CLAUDECODE env var.\n return Boolean(process.env.CLAUDECODE);\n }\n\n getSkillTargetDir(\n skillName: string,\n scope: SkillScope,\n projectRoot?: string,\n ): string {\n const base =\n scope === 'global'\n ? path.join(os.homedir(), '.claude')\n : path.join(projectRoot ?? this.getProjectRoot(), '.claude');\n return path.join(base, 'skills', skillName);\n }\n}\n","import type { SkillIde } from '@teamix-evo/registry';\nimport type { IdeAdapter } from './IdeAdapter.js';\nimport { QoderAdapter } from './QoderAdapter.js';\nimport { ClaudeAdapter } from './ClaudeAdapter.js';\n\nexport type { IdeAdapter } from './IdeAdapter.js';\nexport { QoderAdapter } from './QoderAdapter.js';\nexport { ClaudeAdapter } from './ClaudeAdapter.js';\n\n/** All supported IDE kinds (also default selection set for skills) */\nexport const ALL_IDE_KINDS: readonly SkillIde[] = ['qoder', 'claude'] as const;\n\n/**\n * Get the adapter for a specific IDE kind.\n */\nexport function getAdapter(kind: SkillIde): IdeAdapter {\n switch (kind) {\n case 'qoder':\n return new QoderAdapter();\n case 'claude':\n return new ClaudeAdapter();\n default: {\n const _exhaustive: never = kind;\n throw new Error(`Unsupported IDE kind: ${_exhaustive as string}`);\n }\n }\n}\n\n/**\n * Detect the current IDE environment and return the appropriate adapter.\n * MVP: prefers Qoder; falls back to Claude if CLAUDECODE env is set.\n */\nexport function detectIde(): IdeAdapter {\n const claude = new ClaudeAdapter();\n if (claude.detectIde()) return claude;\n return new QoderAdapter();\n}\n","import Handlebars from 'handlebars';\nimport * as fs from 'node:fs/promises';\n\n// Register custom helpers\nHandlebars.registerHelper('lowercase', (str: unknown) => {\n return typeof str === 'string'\n ? str.toLowerCase()\n : String(str ?? '').toLowerCase();\n});\n\n/** LRU-style compilation cache to avoid recompiling the same template */\nconst compiledCache = new Map<string, HandlebarsTemplateDelegate>();\nconst MAX_CACHE_SIZE = 64;\n\nfunction getCompiledTemplate(\n templateContent: string,\n): HandlebarsTemplateDelegate {\n let compiled = compiledCache.get(templateContent);\n if (!compiled) {\n if (compiledCache.size >= MAX_CACHE_SIZE) {\n // Evict oldest entry\n const firstKey = compiledCache.keys().next().value!;\n compiledCache.delete(firstKey);\n }\n compiled = Handlebars.compile(templateContent, { noEscape: true });\n compiledCache.set(templateContent, compiled);\n }\n return compiled;\n}\n\n/**\n * Render a Handlebars template string with the given data.\n */\nexport function renderTemplate(\n templateContent: string,\n data: Record<string, unknown>,\n): string {\n const compiled = getCompiledTemplate(templateContent);\n return compiled(data);\n}\n\n/**\n * Load template file content from disk.\n */\nexport async function loadTemplateFile(filePath: string): Promise<string> {\n return fs.readFile(filePath, 'utf-8');\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Resolve a source path — handles _template/ prefix by resolving from packageRoot.\n */\nexport function resolveSourcePath(\n source: string,\n variantDir: string,\n packageRoot: string,\n): string {\n if (source.startsWith('_template/')) {\n return path.join(packageRoot, source);\n }\n return path.join(variantDir, source);\n}\n\n/**\n * Common directory names to skip when walking user project trees.\n */\nexport const DEFAULT_SKIP_DIRS = new Set([\n 'node_modules',\n 'dist',\n 'build',\n '.teamix-evo',\n]);\n\n/**\n * Recursively walk a directory and return all file paths.\n * When `skipDirs` is provided, directories whose names are in the set will not\n * be entered — this avoids the cost of recursing into large trees like\n * `node_modules/` only to discard results later.\n */\nexport async function walkDir(\n dir: string,\n skipDirs?: Set<string>,\n): Promise<string[]> {\n const files: string[] = [];\n const entries = await fs.readdir(dir, { withFileTypes: true });\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (skipDirs && skipDirs.has(entry.name)) continue;\n files.push(...(await walkDir(fullPath, skipDirs)));\n } else if (entry.isFile()) {\n files.push(fullPath);\n }\n }\n\n return files;\n}\n\n/**\n * Locate the root directory of an installed npm package by resolving its\n * `package.json`. Used to read token source CSS and variant manifests.\n */\nexport function resolveTokensPackageRoot(packageName: string): string {\n const pkgJson = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJson);\n}\n","import * as path from 'node:path';\nimport { writeFileSafe, fileExists } from './fs.js';\nimport { getErrorMessage } from './error.js';\nimport { logger } from './logger.js';\n\n/**\n * `.mcp.json` content launched by Cursor / Claude Code / Cline.\n *\n * Kept in sync with the scaffold writer in `@teamix-evo/create`. Any change\n * here MUST be mirrored there (see `packages/create/src/orchestrator.ts`).\n */\nconst MCP_JSON_CONTENT = {\n mcpServers: {\n 'teamix-evo': {\n command: 'npx',\n args: ['-y', '@teamix-evo/mcp'],\n },\n },\n} as const;\n\n/**\n * Ensure that `<projectRoot>/.mcp.json` exists.\n *\n * This is called from the incremental entry points (`tokens init`, `skills\n * add`, `ui init`) so projects that adopted teamix-evo without `create` still\n * get the MCP wiring (#BUG-103). Existing files are never overwritten — users\n * may have customised them.\n *\n * Returns `'created'` on first write, `'exists'` if a file is already present,\n * `'failed'` if writing failed (logged as a warning; never throws).\n */\nexport async function ensureMcpJson(\n projectRoot: string,\n): Promise<'created' | 'exists' | 'failed'> {\n const mcpPath = path.join(projectRoot, '.mcp.json');\n if (await fileExists(mcpPath)) return 'exists';\n try {\n await writeFileSafe(\n mcpPath,\n JSON.stringify(MCP_JSON_CONTENT, null, 2) + '\\n',\n );\n logger.debug(`Wrote .mcp.json → ${mcpPath}`);\n return 'created';\n } catch (err) {\n logger.warn(`Failed to write .mcp.json: ${getErrorMessage(err)}`);\n return 'failed';\n }\n}\n","import type {\n ProjectConfig,\n InstalledManifest,\n InstalledResource,\n SkillIde,\n SkillScope,\n SkillsLock,\n SkillsPackageManifest,\n} from '@teamix-evo/registry';\nimport { loadSkillsData } from './skills-client.js';\nimport {\n installSkills,\n updateSkills,\n pruneEmptyIdeSkillDirs,\n} from './skills-installer.js';\nimport {\n ensureTeamixDir,\n readProjectConfig,\n writeProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n readSkillsLock,\n writeSkillsLock,\n readTokensVariant,\n} from './state.js';\nimport { logger } from '../utils/logger.js';\nimport { ensureMcpJson } from '../utils/mcp.js';\n\nconst DEFAULT_SKILLS_PACKAGE = '@teamix-evo/skills';\nconst FLAT_VARIANT = '_flat';\n\n// ─── runSkillsInit ────────────────────────────────────────────────────────────\n// Bulk bootstrap: install every skill in the manifest that matches the current\n// tokens variant + install scope (per ADR 0033). No skill ids accepted —\n// granular adds go through `runSkillsAdd`. Verb split per ADR 0034.\n\nexport interface RunSkillsInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Target IDEs to inject skills into. Required (bulk has no fallback source). */\n ides: readonly SkillIde[];\n /** Install scope. Required (bulk has no fallback source). */\n scope: SkillScope;\n /** IDE identifier written into config.ide when bootstrapping a fresh config (defaults to \"qoder\"). */\n ide?: string;\n /** Override the skills package name (defaults to \"@teamix-evo/skills\"). */\n packageName?: string;\n}\n\nexport type RunSkillsInitResult =\n | {\n status: 'installed';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n skillCount: number;\n fileCount: number;\n resources: InstalledResource[];\n addedSkillIds: string[];\n skippedSkillIds: string[];\n /**\n * Skill ids that were auto-upgraded because their locked version was\n * older than the manifest version.\n */\n autoUpdatedSkillIds: string[];\n /**\n * @deprecated Outdated skills are now auto-upgraded; kept for compat.\n */\n outdatedSkills: OutdatedSkillInfo[];\n }\n | {\n /** Returned when a skills package is already installed and bulk has nothing new to add. */\n status: 'already-initialized';\n };\n\n/**\n * Programmatic equivalent of `teamix-evo skills init`.\n *\n * Installs every manifest skill that matches the current tokens variant +\n * install scope (per ADR 0033 scope filter). Re-running on a project whose\n * `packages.skills` is already configured AND has no missing candidates\n * returns `'already-initialized'`.\n */\nexport async function runSkillsInit(\n options: RunSkillsInitOptions,\n): Promise<RunSkillsInitResult> {\n const { projectRoot } = options;\n const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;\n const ides = [...options.ides] as SkillIde[];\n const scope = options.scope;\n if (ides.length === 0) {\n throw new Error('At least one IDE must be selected.');\n }\n\n await ensureTeamixDir(projectRoot);\n const existingConfig = await readProjectConfig(projectRoot);\n const existingSkillsCfg = existingConfig?.packages?.skills;\n\n const { manifest, data, packageRoot } = await loadSkillsData(packageName);\n const currentTokensVariant = await readTokensVariant(projectRoot);\n\n const existing = await readExistingState(projectRoot, packageName);\n\n // ADR 0033 + tokens variant: filter manifest skills to those eligible for\n // this install scope and current variant.\n const candidateIds = manifest.skills\n .filter((s) => {\n const effectiveScope = s.scope ?? 'project';\n if (effectiveScope !== scope) {\n logger.debug(\n `Skipping skill \"${s.id}\" (scope=${effectiveScope}): current install scope is \"${scope}\". Use \\`skills add ${s.id} --scope ${effectiveScope}\\` to install.`,\n );\n return false;\n }\n if (!s.variant) return true;\n if (!currentTokensVariant) {\n logger.debug(\n `Skipping variant-bound skill \"${s.id}\" (variant=${s.variant}): no tokens variant installed; will be picked up when \"tokens init\" runs.`,\n );\n return false;\n }\n if (s.variant !== currentTokensVariant) {\n logger.debug(\n `Skipping variant-bound skill \"${s.id}\" (variant=${s.variant}): current tokens variant is \"${currentTokensVariant}\".`,\n );\n return false;\n }\n return true;\n })\n .map((s) => s.id);\n\n // Partition candidate skills the same way `runSkillsAdd` does: brand-new go\n // to `onlyIds`; already installed and at-or-above manifest version go to\n // `skippedSkillIds`; already installed but with `lock.version < manifest.version`\n // surface as `outdatedSkills` so callers can suggest `skills update <id>`.\n const { onlyIds, skippedSkillIds, outdatedSkills } = partitionByVersion(\n candidateIds,\n manifest,\n existing,\n );\n\n // Idempotent fast path: nothing new and nothing outdated. Preserve the\n // historical `already-initialized` status only when there's literally\n // nothing for the caller to act on; if any skill is outdated we fall\n // through to the empty-install fast path below so the upgrade hint is\n // surfaced to the CLI layer.\n if (\n existingSkillsCfg &&\n onlyIds.length === 0 &&\n outdatedSkills.length === 0\n ) {\n return { status: 'already-initialized' };\n }\n\n // Empty-install fast path mirrors `runSkillsAdd`: nothing new to install,\n // but at least one outdated skill needs to be auto-upgraded.\n if (onlyIds.length === 0) {\n let autoUpdatedSkillIds: string[] = [];\n if (outdatedSkills.length > 0) {\n autoUpdatedSkillIds = await autoUpgradeOutdatedSkills({\n projectRoot,\n packageName,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n outdatedSkills,\n existing,\n existingConfig,\n });\n }\n return {\n status: 'installed',\n packageName,\n version: manifest.version,\n ides,\n scope,\n skillCount: 0,\n fileCount: 0,\n resources: [],\n addedSkillIds: [],\n skippedSkillIds,\n autoUpdatedSkillIds,\n outdatedSkills: [],\n };\n }\n\n return finalizeSkillsInstall({\n projectRoot,\n packageName,\n ideIdent: options.ide ?? 'qoder',\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n skippedSkillIds,\n outdatedSkills,\n existing,\n existingConfig,\n });\n}\n\n// ─── runSkillsAdd ─────────────────────────────────────────────────────────────\n// Incremental: install named skill ids. `names` is required (≥ 1).\n// Skills already present are skipped. ADR 0034.\n\nexport interface RunSkillsAddOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /**\n * Skill ids to add. **Required, must contain at least one id.** Use\n * {@link runSkillsInit} for bulk bootstrap (no ids).\n */\n names: readonly string[];\n /** Target IDEs. Optional — falls back to the previously installed config. */\n ides?: readonly SkillIde[];\n /** Install scope. Optional — falls back to existing config. */\n scope?: SkillScope;\n /** IDE identifier written into config.ide when bootstrapping a fresh config (defaults to \"qoder\"). */\n ide?: string;\n /** Override the skills package name (defaults to \"@teamix-evo/skills\"). */\n packageName?: string;\n}\n\n/**\n * Detail for an already-installed skill whose locked version is older than\n * the manifest's latest version. Use `skills update <id>` to upgrade.\n */\nexport interface OutdatedSkillInfo {\n /** Skill id */\n id: string;\n /** Version recorded in `.teamix-evo/skills.lock.json` */\n installed: string;\n /** Version available in the upstream manifest (i.e. `npx` resolved `@latest`) */\n latest: string;\n}\n\nexport type RunSkillsAddResult = {\n status: 'installed';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n /** Number of skills that were freshly added in this call. */\n skillCount: number;\n /** Number of files written by `installSkills` for the freshly added skills. */\n fileCount: number;\n /** InstalledResource records for the freshly added skills only. */\n resources: InstalledResource[];\n /** Skill ids that were freshly added in this call. */\n addedSkillIds: string[];\n /**\n * Skill ids that were requested but already installed at the latest version;\n * nothing to do.\n */\n skippedSkillIds: string[];\n /**\n * Skill ids that were auto-upgraded because their locked version was older\n * than the manifest version.\n */\n autoUpdatedSkillIds: string[];\n /**\n * @deprecated Outdated skills are now auto-upgraded; this array is always\n * empty. Kept for backward-compatible callers; will be removed in next major.\n */\n outdatedSkills: OutdatedSkillInfo[];\n};\n\n/**\n * Programmatic equivalent of `teamix-evo skills add <names...>` (ADR 0034).\n *\n * Installs only the listed skills. Skills already present are skipped (use\n * `skills update` to refresh). `ides` / `scope` may be omitted — they fall\n * back to the previously installed config.\n *\n * Throws if `names` is empty — bulk bootstrap belongs to {@link runSkillsInit}.\n */\nexport async function runSkillsAdd(\n options: RunSkillsAddOptions,\n): Promise<RunSkillsAddResult> {\n if (!options.names || options.names.length === 0) {\n throw new Error(\n 'runSkillsAdd requires at least one skill id. Use runSkillsInit() for bulk install.',\n );\n }\n\n const { projectRoot, names: requestedNames } = options;\n const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;\n\n await ensureTeamixDir(projectRoot);\n\n const existingConfig = await readProjectConfig(projectRoot);\n const existingSkillsCfg = existingConfig?.packages?.skills;\n\n // Resolve ides/scope: explicit option wins, else fall back to existing config.\n const ides = (\n options.ides && options.ides.length > 0\n ? [...options.ides]\n : existingSkillsCfg?.ides\n ? [...existingSkillsCfg.ides]\n : []\n ) as SkillIde[];\n const scope = (options.scope ?? existingSkillsCfg?.scope) as\n | SkillScope\n | undefined;\n if (ides.length === 0) {\n throw new Error('At least one IDE must be selected.');\n }\n if (!scope) {\n throw new Error('Scope must be specified (project | global).');\n }\n\n const { manifest, data, packageRoot } = await loadSkillsData(packageName);\n\n // Validate requested names against manifest.\n const known = new Set(manifest.skills.map((s) => s.id));\n const unknown = requestedNames.filter((n) => !known.has(n));\n if (unknown.length > 0) {\n const available = [...known].join(', ');\n throw new Error(\n `Unknown skill id(s): ${unknown.join(', ')}. Available: ${\n available || '(none)'\n }.`,\n );\n }\n\n // ADR 0033: warn when explicitly naming a skill whose declared scope\n // doesn't match the current install scope. Don't block — explicit\n // naming overrides the default; user takes responsibility.\n for (const s of manifest.skills) {\n if (requestedNames.includes(s.id) && s.scope && s.scope !== scope) {\n logger.warn(\n `\"${s.id}\" 推荐 ${s.scope} scope 安装。当前以 ${scope} scope 强制安装,可能与另一 scope 的副本冲突。建议改用 \\`skills add ${s.id} --scope ${s.scope}\\`。`,\n );\n }\n }\n\n const existing = await readExistingState(projectRoot, packageName);\n\n // Partition requested names: already-installed-and-up-to-date go to\n // `skippedSkillIds`; already-installed-but-older go to `outdatedSkills`\n // (caller surfaces an upgrade hint); brand-new go to `onlyIds`.\n const { onlyIds, skippedSkillIds, outdatedSkills } = partitionByVersion(\n requestedNames,\n manifest,\n existing,\n );\n\n // Incremental fast path: nothing new to install. But if there are\n // outdated skills, auto-upgrade them before returning.\n if (onlyIds.length === 0) {\n let autoUpdatedSkillIds: string[] = [];\n if (outdatedSkills.length > 0) {\n autoUpdatedSkillIds = await autoUpgradeOutdatedSkills({\n projectRoot,\n packageName,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n outdatedSkills,\n existing,\n existingConfig,\n });\n }\n return {\n status: 'installed',\n packageName,\n version: manifest.version,\n ides,\n scope,\n skillCount: 0,\n fileCount: 0,\n resources: [],\n addedSkillIds: [],\n skippedSkillIds,\n autoUpdatedSkillIds,\n outdatedSkills: [],\n };\n }\n\n return finalizeSkillsInstall({\n projectRoot,\n packageName,\n ideIdent: options.ide ?? 'qoder',\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n skippedSkillIds,\n outdatedSkills,\n existing,\n existingConfig,\n });\n}\n\n// ─── partition helper (shared by init + add) ────────────────────────────────\n// Split a list of skill ids into three buckets based on `existing` lock state\n// vs `manifest` version. `onlyIds` (new) → drives `installSkills`;\n// `skippedSkillIds` (already at latest) and `outdatedSkills` (lock < manifest)\n// are surfaced to the CLI for messaging. Pre-ADR-0013 legacy installs whose\n// lock is missing fall through to `skippedSkillIds` (conservative — don't\n// nag a user we can't reliably version-check).\nfunction partitionByVersion(\n ids: readonly string[],\n manifest: SkillsPackageManifest,\n existing: ExistingState,\n): {\n onlyIds: string[];\n skippedSkillIds: string[];\n outdatedSkills: OutdatedSkillInfo[];\n} {\n const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));\n const onlyIds: string[] = [];\n const skippedSkillIds: string[] = [];\n const outdatedSkills: OutdatedSkillInfo[] = [];\n for (const name of ids) {\n if (!existing.skillIds.has(name)) {\n onlyIds.push(name);\n continue;\n }\n const installedVer = existing.lock?.skills?.[name]?.version;\n const latestVer = manifestById.get(name)?.version;\n if (\n installedVer &&\n latestVer &&\n compareSemver(installedVer, latestVer) < 0\n ) {\n outdatedSkills.push({\n id: name,\n installed: installedVer,\n latest: latestVer,\n });\n } else {\n skippedSkillIds.push(name);\n }\n }\n return { onlyIds, skippedSkillIds, outdatedSkills };\n}\n\n// ─── semver helpers (light, no dep) ───────────────────────────────────────────\n// Only needed by `runSkillsAdd` to decide whether an already-installed skill is\n// truly outdated (installed < manifest). We deliberately avoid pulling in a\n// `semver` runtime dep; manifest versions are validated against\n// `^\\d+\\.\\d+\\.\\d+/` by the registry schema, so a numeric major.minor.patch\n// triple is sufficient. Pre-release / build metadata is ignored — if two\n// versions share the same triple they're considered equal here.\nfunction parseSemverTriple(v: string): [number, number, number] | null {\n const m = /^(\\d+)\\.(\\d+)\\.(\\d+)/.exec(v);\n if (!m) return null;\n return [Number(m[1]), Number(m[2]), Number(m[3])];\n}\n\n/** -1 if a < b, 0 if equal (or unparseable + identical strings), 1 if a > b. */\nfunction compareSemver(a: string, b: string): number {\n const pa = parseSemverTriple(a);\n const pb = parseSemverTriple(b);\n if (!pa || !pb) {\n if (a === b) return 0;\n return a < b ? -1 : 1;\n }\n for (let i = 0; i < 3; i++) {\n if (pa[i]! !== pb[i]!) return pa[i]! < pb[i]! ? -1 : 1;\n }\n return 0;\n}\n\n// ─── shared internals ─────────────────────────────────────────────────────────\n\ninterface ExistingState {\n installed: InstalledManifest | null;\n pkg:\n | {\n package: string;\n resources: InstalledResource[];\n }\n | undefined;\n lock: SkillsLock | null;\n skillIds: Set<string>;\n}\n\nasync function readExistingState(\n projectRoot: string,\n packageName: string,\n): Promise<ExistingState> {\n const installed = await readInstalledManifest(projectRoot);\n const pkg = installed?.installed.find((p) => p.package === packageName);\n const lock = await readSkillsLock(projectRoot);\n const skillIds = new Set<string>([\n ...Object.keys(lock?.skills ?? {}),\n // Legacy fallback: pre-ADR-0013 installs only had manifest.json. Derive\n // skill ids by stripping the trailing :source / :sub-file suffix.\n ...(pkg?.resources ?? []).map((r) => r.id.split(':')[0] ?? r.id),\n ]);\n return { installed, pkg, lock, skillIds };\n}\n\ninterface FinalizeArgs {\n projectRoot: string;\n packageName: string;\n ideIdent: string;\n manifest: SkillsPackageManifest;\n data: Parameters<typeof installSkills>[0]['data'];\n packageRoot: string;\n ides: SkillIde[];\n scope: SkillScope;\n onlyIds: string[];\n skippedSkillIds: string[];\n /** Optional — only populated by `runSkillsAdd`. `runSkillsInit` leaves empty. */\n outdatedSkills?: OutdatedSkillInfo[];\n existing: ExistingState;\n existingConfig: ProjectConfig | null;\n}\n\nasync function finalizeSkillsInstall(args: FinalizeArgs): Promise<{\n status: 'installed';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n skillCount: number;\n fileCount: number;\n resources: InstalledResource[];\n addedSkillIds: string[];\n skippedSkillIds: string[];\n autoUpdatedSkillIds: string[];\n outdatedSkills: OutdatedSkillInfo[];\n}> {\n const {\n projectRoot,\n packageName,\n ideIdent,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n skippedSkillIds,\n outdatedSkills,\n existing,\n existingConfig,\n } = args;\n\n const result = await installSkills({\n projectRoot,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds,\n });\n\n const config: ProjectConfig = existingConfig ?? {\n $schema: 'https://teamix-evo.dev/schema/config/v2.json',\n schemaVersion: 2,\n ide: ideIdent,\n packages: {},\n };\n config.packages.skills = {\n variant: FLAT_VARIANT,\n version: manifest.version,\n ides,\n scope,\n };\n await writeProjectConfig(projectRoot, config);\n\n const installedAt = new Date().toISOString();\n const installedManifest: InstalledManifest = existing.installed ?? {\n schemaVersion: 1,\n installed: [],\n };\n const idx = installedManifest.installed.findIndex(\n (p) => p.package === packageName,\n );\n const mergedResources = mergeInstalledResources(\n existing.pkg?.resources ?? [],\n result.resources,\n );\n const entry = {\n package: packageName,\n variant: FLAT_VARIANT,\n version: manifest.version,\n installedAt,\n resources: mergedResources,\n };\n if (idx >= 0) installedManifest.installed[idx] = entry;\n else installedManifest.installed.push(entry);\n await writeInstalledManifest(projectRoot, installedManifest);\n\n // Update skills source-mirror lock (per ADR 0013).\n const lock: SkillsLock = existing.lock ?? {\n schemaVersion: 1,\n skills: {},\n };\n for (const skillId of onlyIds) {\n const skillDef = manifest.skills.find((s) => s.id === skillId);\n if (!skillDef) continue;\n const mirroredTo = skillDef.ides.filter((i) => ides.includes(i));\n lock.skills[skillId] = {\n version: skillDef.version,\n from: packageName,\n installedAt,\n scope,\n mirroredTo,\n };\n }\n await writeSkillsLock(projectRoot, lock);\n\n // After the install completes, ensure the MCP launcher config exists so\n // Cursor / Claude Code / Cline pick up `@teamix-evo/mcp` automatically\n // (#BUG-103). Existing `.mcp.json` files are preserved.\n await ensureMcpJson(projectRoot);\n\n // Phase 5.G: sweep empty IDE skill dirs left over from prior installs\n // (e.g. a removed upstream skill). Best-effort — swallows errors.\n try {\n await pruneEmptyIdeSkillDirs({ projectRoot, ides, scope });\n } catch {\n // Cleanup is decoration; never a hard failure.\n }\n\n // Auto-upgrade outdated skills alongside the fresh install.\n let autoUpdatedSkillIds: string[] = [];\n if (outdatedSkills && outdatedSkills.length > 0) {\n autoUpdatedSkillIds = await autoUpgradeOutdatedSkills({\n projectRoot,\n packageName,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n outdatedSkills,\n existing,\n existingConfig: existingConfig ?? config,\n });\n }\n\n return {\n status: 'installed',\n packageName,\n version: manifest.version,\n ides,\n scope,\n skillCount: onlyIds.length,\n fileCount: result.count,\n resources: result.resources,\n addedSkillIds: onlyIds,\n skippedSkillIds,\n autoUpdatedSkillIds,\n outdatedSkills: [],\n };\n}\n\nfunction mergeInstalledResources(\n existing: InstalledResource[],\n next: InstalledResource[],\n): InstalledResource[] {\n const map = new Map<string, InstalledResource>();\n const key = (r: InstalledResource): string =>\n `${r.id}|${r.ide ?? ''}|${r.scope ?? ''}`;\n for (const r of existing) map.set(key(r), r);\n for (const r of next) map.set(key(r), r);\n return [...map.values()];\n}\n\n// ─── auto-upgrade outdated skills ──────────────────────────────────────────────\n// When `skills add` detects already-installed skills whose locked version is\n// older than the manifest version, we auto-upgrade them in-place rather than\n// just surfacing a hint. This ensures the client-side AI always uses the latest\n// skill version available in the resolved `@latest` package.\n\ninterface AutoUpgradeArgs {\n projectRoot: string;\n packageName: string;\n manifest: SkillsPackageManifest;\n data: Parameters<typeof installSkills>[0]['data'];\n packageRoot: string;\n ides: SkillIde[];\n scope: SkillScope;\n outdatedSkills: OutdatedSkillInfo[];\n existing: ExistingState;\n existingConfig: ProjectConfig | null;\n}\n\nasync function autoUpgradeOutdatedSkills(\n args: AutoUpgradeArgs,\n): Promise<string[]> {\n const {\n projectRoot,\n packageName,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n outdatedSkills,\n existing,\n } = args;\n\n const targetIds = outdatedSkills.map((o) => o.id);\n\n // Use the updateSkills flow which preserves managed regions.\n await updateSkills({\n projectRoot,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds: targetIds,\n });\n\n // Update the lock for auto-upgraded skills.\n const lock: SkillsLock = existing.lock ?? {\n schemaVersion: 1,\n skills: {},\n };\n const installedAt = new Date().toISOString();\n const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));\n for (const id of targetIds) {\n const skillDef = manifestById.get(id);\n if (!skillDef) continue;\n const mirroredTo = skillDef.ides.filter((i) => ides.includes(i));\n lock.skills[id] = {\n version: skillDef.version,\n from: packageName,\n installedAt,\n scope,\n mirroredTo,\n };\n }\n await writeSkillsLock(projectRoot, lock);\n\n // Update installed manifest resources for upgraded skills.\n const installedManifest = (await readInstalledManifest(projectRoot)) ?? {\n schemaVersion: 1 as const,\n installed: [],\n };\n const idx = installedManifest.installed.findIndex(\n (p) => p.package === packageName,\n );\n if (idx >= 0) {\n installedManifest.installed[idx]!.version = manifest.version;\n installedManifest.installed[idx]!.installedAt = installedAt;\n }\n await writeInstalledManifest(projectRoot, installedManifest);\n\n logger.debug(\n `Auto-upgraded ${targetIds.length} outdated skill(s): ${targetIds.join(\n ', ',\n )}`,\n );\n\n return targetIds;\n}\n","import type {\n InstalledResource,\n SkillIde,\n SkillScope,\n SkillsLock,\n} from '@teamix-evo/registry';\nimport { loadSkillsData } from './skills-client.js';\nimport { updateSkills } from './skills-installer.js';\nimport {\n readProjectConfig,\n readInstalledManifest,\n writeProjectConfig,\n writeInstalledManifest,\n readSkillsLock,\n writeSkillsLock,\n} from './state.js';\nimport { logger } from '../utils/logger.js';\n\nconst DEFAULT_SKILLS_PACKAGE = '@teamix-evo/skills';\nconst FLAT_VARIANT = '_flat';\n\n// ─── runSkillsUpdate ──────────────────────────────────────────────────────────\n// ADR 0035: update only refreshes skills that are (a) recorded in the lock and\n// (b) match the current install scope. New skills added to the manifest are NOT\n// auto-installed by update — use `skills add <id>` for that. version-diff\n// short-circuits when nothing has actually changed.\n\nexport interface RunSkillsUpdateOptions {\n /** Absolute project (or global meta) root. */\n projectRoot: string;\n /**\n * Optional: limit the update to these skill ids. Falls back to \"every\n * skill in lock that matches the current install scope\".\n */\n names?: readonly string[];\n /** When true, plan only — no source rewrite, no mirror, no lock write. */\n dryRun?: boolean;\n /** Override the skills package name (defaults to `@teamix-evo/skills`). */\n packageName?: string;\n}\n\nexport interface UpdatePlanItem {\n id: string;\n current: string;\n next: string;\n /** Same as updateStrategy semantics, computed from the manifest. */\n strategy: 'frozen' | 'regenerable' | 'managed';\n /**\n * Predicted action for this skill source file in non-dryRun mode.\n * - `up-to-date` — version unchanged; safe to skip\n * - `version-bump` — version changed; will overwrite/merge per strategy\n */\n action: 'up-to-date' | 'version-bump';\n}\n\nexport type RunSkillsUpdateResult =\n | { status: 'no-skills' }\n | {\n status: 'no-changes';\n packageName: string;\n version: string;\n checkedSkillIds: string[];\n }\n | {\n status: 'dry-run';\n packageName: string;\n currentVersion: string;\n availableVersion: string;\n plan: UpdatePlanItem[];\n }\n | {\n status: 'updated';\n packageName: string;\n version: string;\n ides: SkillIde[];\n scope: SkillScope;\n updatedSkillIds: string[];\n skippedSkillIds: string[];\n summary: { overwritten: number; managed: number; skipped: number; created: number };\n resources: InstalledResource[];\n };\n\n/**\n * Programmatic equivalent of `teamix-evo skills update [names...] [--dry-run]`.\n *\n * Per ADR 0035:\n * 1. Range = `keys(lock.skills) ∩ scope-match ∩ (names if given)`\n * 2. version-diff short-circuit when every target id has the same lock\n * version as the manifest\n * 3. New skills (not in lock) are NEVER auto-installed by update\n * 4. lock writeback only touches `targetIds` — existing entries are preserved\n */\nexport async function runSkillsUpdate(\n options: RunSkillsUpdateOptions,\n): Promise<RunSkillsUpdateResult> {\n const { projectRoot, names: requestedNames, dryRun } = options;\n const packageName = options.packageName ?? DEFAULT_SKILLS_PACKAGE;\n\n const config = await readProjectConfig(projectRoot);\n const skillsCfg = config?.packages?.skills;\n if (!skillsCfg) {\n return { status: 'no-skills' };\n }\n\n const ides = (skillsCfg.ides ?? ['qoder', 'claude']) as SkillIde[];\n const scope = (skillsCfg.scope ?? 'project') as SkillScope;\n\n const existingLock = await readSkillsLock(projectRoot);\n if (!existingLock || Object.keys(existingLock.skills).length === 0) {\n return { status: 'no-skills' };\n }\n\n const { manifest, data, packageRoot } = await loadSkillsData(packageName);\n const manifestById = new Map(manifest.skills.map((s) => [s.id, s]));\n\n // Three-gate intersection: lock ∩ scope ∩ names.\n const lockIds = Object.keys(existingLock.skills);\n const requestedSet = requestedNames ? new Set(requestedNames) : null;\n if (requestedSet) {\n const unknown = requestedNames!.filter(\n (n) => !lockIds.includes(n) && !manifestById.has(n),\n );\n if (unknown.length > 0) {\n throw new Error(\n `Unknown skill id(s): ${unknown.join(\n ', ',\n )}. Available (installed): ${lockIds.join(', ') || '(none)'}.`,\n );\n }\n }\n\n const targetIds: string[] = [];\n const skippedSkillIds: string[] = [];\n for (const id of lockIds) {\n if (requestedSet && !requestedSet.has(id)) continue;\n const entry = manifestById.get(id);\n if (!entry) {\n // Lock has it, manifest no longer does (skill removed upstream).\n // Skip without error — uninstall is the user's call.\n logger.debug(\n `Skipping \"${id}\": no longer in upstream manifest. Use \\`skills uninstall ${id}\\` to remove.`,\n );\n skippedSkillIds.push(id);\n continue;\n }\n const effectiveScope = entry.scope ?? 'project';\n if (effectiveScope !== scope) {\n logger.debug(\n `Skipping \"${id}\" (scope=${effectiveScope}): current install scope is \"${scope}\".`,\n );\n skippedSkillIds.push(id);\n continue;\n }\n targetIds.push(id);\n }\n\n // version-diff short-circuit\n const allSame = targetIds.every((id) => {\n const lockVer = existingLock.skills[id]!.version;\n const manVer = manifestById.get(id)!.version;\n return lockVer === manVer;\n });\n if (targetIds.length > 0 && allSame && !dryRun) {\n return {\n status: 'no-changes',\n packageName,\n version: manifest.version,\n checkedSkillIds: targetIds,\n };\n }\n\n if (dryRun) {\n const plan: UpdatePlanItem[] = targetIds.map((id) => {\n const lockVer = existingLock.skills[id]!.version;\n const entry = manifestById.get(id)!;\n const sameVersion = lockVer === entry.version;\n return {\n id,\n current: lockVer,\n next: entry.version,\n strategy: entry.updateStrategy ?? 'managed',\n action: sameVersion ? 'up-to-date' : 'version-bump',\n };\n });\n return {\n status: 'dry-run',\n packageName,\n currentVersion: skillsCfg.version,\n availableVersion: manifest.version,\n plan,\n };\n }\n\n if (targetIds.length === 0) {\n return {\n status: 'updated',\n packageName,\n version: manifest.version,\n ides,\n scope,\n updatedSkillIds: [],\n skippedSkillIds,\n summary: { overwritten: 0, managed: 0, skipped: 0, created: 0 },\n resources: [],\n };\n }\n\n const result = await updateSkills({\n projectRoot,\n manifest,\n data,\n packageRoot,\n ides,\n scope,\n onlyIds: targetIds,\n });\n\n // Update config.version (track the package-level version we last consumed).\n config!.packages.skills = {\n ...skillsCfg,\n version: manifest.version,\n };\n await writeProjectConfig(projectRoot, config!);\n\n // Update installed manifest (replace the package-level entry's resources).\n const installedManifest = (await readInstalledManifest(projectRoot)) ?? {\n schemaVersion: 1 as const,\n installed: [],\n };\n const idx = installedManifest.installed.findIndex(\n (p) => p.package === packageName,\n );\n const installedAt = new Date().toISOString();\n // Merge: keep resources from skills NOT in targetIds (preserve existing\n // entries for skills we didn't touch this round).\n const prior = idx >= 0 ? installedManifest.installed[idx]!.resources : [];\n const targetSet = new Set(targetIds);\n const preserved = prior.filter((r) => {\n const skillId = r.id.split(':')[0];\n return skillId ? !targetSet.has(skillId) : true;\n });\n const entry = {\n package: packageName,\n variant: FLAT_VARIANT,\n version: manifest.version,\n installedAt,\n resources: [...preserved, ...result.resources],\n };\n if (idx >= 0) installedManifest.installed[idx] = entry;\n else installedManifest.installed.push(entry);\n await writeInstalledManifest(projectRoot, installedManifest);\n\n // Update lock — only for targetIds, preserving other entries.\n const lock: SkillsLock = {\n schemaVersion: 1,\n skills: { ...existingLock.skills },\n };\n for (const id of targetIds) {\n const skillDef = manifestById.get(id);\n if (!skillDef) continue;\n const mirroredTo = skillDef.ides.filter((i) => ides.includes(i));\n lock.skills[id] = {\n version: skillDef.version,\n from: packageName,\n installedAt,\n scope,\n mirroredTo,\n };\n }\n await writeSkillsLock(projectRoot, lock);\n\n return {\n status: 'updated',\n packageName,\n version: manifest.version,\n ides,\n scope,\n updatedSkillIds: targetIds,\n skippedSkillIds,\n summary: result.summary,\n resources: result.resources,\n };\n}\n","import type { ProjectConfig, UiAliases } from '@teamix-evo/registry';\nimport { ensureMcpJson } from '../utils/mcp.js';\nimport {\n ensureTeamixDir,\n readProjectConfig,\n writeProjectConfig,\n} from './state.js';\n\nexport const DEFAULT_UI_ALIASES: UiAliases = {\n components: 'src/components/ui',\n hooks: 'src/hooks',\n utils: 'src/lib/utils',\n lib: 'src/lib',\n business: 'src/components/business',\n blocks: 'src/blocks',\n templates: 'src/templates',\n};\n\nexport const DEFAULT_UI_ICON_LIBRARY = 'lucide';\n\nexport interface RunUiInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Component aliases. Falls back to {@link DEFAULT_UI_ALIASES}. */\n aliases?: Partial<UiAliases>;\n /** Declared icon library (does not trigger code rewrite). Defaults to \"lucide\". */\n iconLibrary?: string;\n /** Whether the project uses TSX (true) or JSX (false). Defaults to true. */\n tsx?: boolean;\n /** Whether the project emits React Server Components markers. Defaults to false. */\n rsc?: boolean;\n /** IDE identifier written into config.ide when bootstrapping a fresh config (defaults to \"qoder\"). */\n ide?: string;\n}\n\nexport type RunUiInitResult =\n | {\n status: 'installed';\n aliases: UiAliases;\n iconLibrary: string;\n tsx: boolean;\n rsc: boolean;\n }\n | {\n status: 'already-initialized';\n };\n\n/**\n * Programmatic equivalent of `teamix-evo ui init`.\n *\n * Writes `packages.ui` into `.teamix-evo/config.json` only — no resource files\n * are touched. Use {@link runUiAdd} afterwards to install component sources.\n */\nexport async function runUiInit(\n options: RunUiInitOptions,\n): Promise<RunUiInitResult> {\n const { projectRoot } = options;\n const ideIdent = options.ide ?? 'qoder';\n\n await ensureTeamixDir(projectRoot);\n\n const existingConfig = await readProjectConfig(projectRoot);\n if (existingConfig?.packages?.ui) {\n return { status: 'already-initialized' };\n }\n\n const aliases: UiAliases = {\n components: options.aliases?.components ?? DEFAULT_UI_ALIASES.components,\n hooks: options.aliases?.hooks ?? DEFAULT_UI_ALIASES.hooks,\n utils: options.aliases?.utils ?? DEFAULT_UI_ALIASES.utils,\n lib: options.aliases?.lib ?? DEFAULT_UI_ALIASES.lib,\n business: options.aliases?.business ?? DEFAULT_UI_ALIASES.business,\n blocks: options.aliases?.blocks ?? DEFAULT_UI_ALIASES.blocks,\n templates: options.aliases?.templates ?? DEFAULT_UI_ALIASES.templates,\n };\n const iconLibrary = options.iconLibrary ?? DEFAULT_UI_ICON_LIBRARY;\n const tsx = options.tsx ?? true;\n const rsc = options.rsc ?? false;\n\n const config: ProjectConfig = existingConfig ?? {\n $schema: 'https://teamix-evo.dev/schema/config/v2.json',\n schemaVersion: 2,\n ide: ideIdent,\n packages: {},\n };\n config.packages.ui = {\n variant: '_flat',\n version: '0.0.0',\n aliases,\n iconLibrary,\n tsx,\n rsc,\n };\n await writeProjectConfig(projectRoot, config);\n\n // Ensure `.mcp.json` exists so editors auto-launch the MCP server even\n // when the user adopted teamix-evo without the create scaffold (#BUG-103).\n await ensureMcpJson(projectRoot);\n\n return {\n status: 'installed',\n aliases,\n iconLibrary,\n tsx,\n rsc,\n };\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport type { UiPackageManifest } from '@teamix-evo/registry';\nimport { loadUiPackageManifest } from '@teamix-evo/registry';\nimport { logger } from '../utils/logger.js';\n\nconst require = createRequire(import.meta.url);\n\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\n/**\n * Load the ui package manifest and optional shared `_data.json`.\n *\n * @param packageName - e.g. \"@teamix-evo/ui\"\n */\nexport async function loadUiData(packageName: string): Promise<{\n manifest: UiPackageManifest;\n data: Record<string, unknown>;\n packageRoot: string;\n}> {\n const packageRoot = resolvePackageRoot(packageName);\n\n logger.debug(`Resolved ui package root: ${packageRoot}`);\n\n const manifest = await loadUiPackageManifest(packageRoot);\n\n let data: Record<string, unknown> = {};\n const dataPath = path.join(packageRoot, '_data.json');\n try {\n const raw = await fs.readFile(dataPath, 'utf-8');\n data = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err;\n }\n logger.debug(`No _data.json found at ${dataPath}, using empty data`);\n }\n\n return { manifest, data, packageRoot };\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport type {\n UiEntry,\n UiPackageManifest,\n UiAliases,\n InstalledResource,\n} from '@teamix-evo/registry';\nimport { resolveUiEntryOrder } from '@teamix-evo/registry';\nimport { backupFile, writeFileSafe, fileExists } from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport { rewriteImports } from '../utils/transform-imports.js';\nimport { logger } from '../utils/logger.js';\nimport { getErrorMessage } from '../utils/error.js';\n\nexport interface UiInstallOptions {\n /** Project root directory */\n projectRoot: string;\n /** UI package manifest */\n manifest: UiPackageManifest;\n /** Absolute ui package root (used to resolve entry source paths) */\n packageRoot: string;\n /**\n * Optional per-entry package root override. When set, entries in the map\n * resolve their `file.source` against the mapped root instead of `packageRoot`.\n * Used by variant-aware packages (biz-ui / templates) that pull in\n * @teamix-evo/ui transitive deps — each entry resolves from its source package.\n */\n entryPackageRoot?: Map<string, string>;\n /** Aliases configured in `packages.ui.aliases` */\n aliases: UiAliases;\n /** Entry ids the user explicitly requested to add */\n requested: string[];\n /** When true, skip writing entries whose target file already exists (frozen-on-add). */\n skipExisting?: boolean;\n /** When false, preserve directory structure in import paths (skip flattenRestPath). Defaults to true. */\n flatten?: boolean;\n}\n\nexport interface UiInstallResult {\n /** Ordered list of entry ids that were processed (deps + requested) */\n orderedIds: string[];\n /** Per-file install records (for InstalledManifest) */\n resources: InstalledResource[];\n /** Aggregate npm dependencies across the installed entries */\n npmDependencies: Record<string, string>;\n /** Number of files written */\n written: number;\n /** Number of files skipped because they already exist (frozen) */\n skipped: number;\n}\n\n/**\n * Install the requested ui entries (transitively resolving registryDependencies).\n * For frozen entries that already exist on disk, the write is skipped — shadcn-style.\n */\nexport async function installUiEntries(\n options: UiInstallOptions,\n): Promise<UiInstallResult> {\n const {\n projectRoot,\n manifest,\n packageRoot,\n entryPackageRoot,\n aliases,\n requested,\n skipExisting = true,\n flatten = true,\n } = options;\n\n const orderedIds = resolveUiEntryOrder(manifest.entries, requested);\n const idToEntry = new Map(manifest.entries.map((e) => [e.id, e]));\n\n const resources: InstalledResource[] = [];\n const npmDeps: Record<string, string> = {};\n let written = 0;\n let skipped = 0;\n\n for (const id of orderedIds) {\n const entry = idToEntry.get(id);\n if (!entry) continue;\n\n // Aggregate npm deps regardless of whether files were written — the user\n // may have manually deleted node_modules; we want to surface the full set.\n if (entry.dependencies) {\n for (const [name, range] of Object.entries(entry.dependencies)) {\n npmDeps[name] = range;\n }\n }\n\n for (const file of entry.files) {\n const targetAbs = resolveTargetPath(projectRoot, aliases, entry, file);\n const exists = await fileExists(targetAbs);\n\n if (\n exists &&\n skipExisting &&\n (entry.updateStrategy ?? 'frozen') === 'frozen'\n ) {\n logger.info(` skip (frozen, exists): ${rel(projectRoot, targetAbs)}`);\n skipped++;\n continue;\n }\n\n const rootForEntry = entryPackageRoot?.get(entry.id) ?? packageRoot;\n const sourceAbs = path.resolve(rootForEntry, file.source);\n const raw = await fs.readFile(sourceAbs, 'utf-8');\n const transformed = rewriteImports(raw, aliases, { flatten });\n // Phase 1.A2: any existing user file we are about to overwrite must be\n // backed up under .teamix-evo/.backups/. This applies to:\n // - regenerable entries on re-install,\n // - frozen entries when caller passes overwrite=true (init conflict\n // decision \"shadcn-source: overwrite\").\n if (exists) {\n await backupFile(targetAbs, projectRoot);\n }\n await writeFileSafe(targetAbs, transformed);\n written++;\n logger.info(` write: ${rel(projectRoot, targetAbs)}`);\n\n resources.push({\n id: `${entry.id}:${file.targetName}`,\n target: targetAbs,\n hash: computeHash(transformed),\n strategy: entry.updateStrategy ?? 'frozen',\n });\n }\n }\n\n return {\n orderedIds,\n resources,\n npmDependencies: npmDeps,\n written,\n skipped,\n };\n}\n\nfunction resolveTargetPath(\n projectRoot: string,\n aliases: UiAliases,\n entry: UiEntry,\n file: { targetAlias: string; targetName: string },\n): string {\n const aliasDir = aliases[file.targetAlias as keyof UiAliases];\n if (!aliasDir) {\n throw new Error(\n `Entry \"${entry.id}\" requires alias \"${file.targetAlias}\" but it is not configured.`,\n );\n }\n return path.join(projectRoot, aliasDir, file.targetName);\n}\n\nfunction rel(projectRoot: string, abs: string): string {\n return path.relative(projectRoot, abs);\n}\n\n/**\n * Remove all installed ui resource files and prune empty parent directories.\n */\nexport async function removeUiFiles(\n records: InstalledResource[],\n): Promise<string[]> {\n const removed: string[] = [];\n for (const r of records) {\n try {\n await fs.unlink(r.target);\n removed.push(r.target);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n logger.warn(`Failed to remove ${r.target}: ${getErrorMessage(err)}`);\n }\n }\n }\n const parents = new Set(records.map((r) => path.dirname(r.target)));\n for (const dir of parents) {\n try {\n const entries = await fs.readdir(dir);\n if (entries.length === 0) await fs.rmdir(dir);\n } catch {\n /* ignore */\n }\n }\n return removed;\n}\n","import type { UiAliases } from '@teamix-evo/registry';\n\n/**\n * Map between the ui package's \"developer-time\" import roots and the user's\n * configured aliases. The keys are the source roots used inside ui source\n * files (e.g. `@/utils/cn` references `src/utils/`).\n */\nconst SOURCE_ROOT_TO_ALIAS_KEY: Record<string, keyof UiAliases> = {\n components: 'components',\n hooks: 'hooks',\n utils: 'utils',\n lib: 'lib',\n blocks: 'blocks',\n};\n\n/**\n * Rewrite import specifiers in a UI source file so that the developer-time\n * placeholders (e.g. `@/utils/cn`) resolve to the user's configured aliases\n * (e.g. `@/lib/utils/cn` when `aliases.utils === \"src/lib/utils\"`).\n *\n * Matches both static imports and dynamic imports of the form `@/<root>/<rest>`.\n * Bare `@/` (no segment) and unknown segments are left untouched.\n *\n * The rewrite uses each user alias verbatim. If the user alias begins with\n * `src/`, that prefix is stripped because TypeScript-style `@/*` → `src/*`\n * mappings expect paths relative to `src`.\n */\nexport function rewriteImports(\n source: string,\n aliases: UiAliases,\n opts?: { flatten?: boolean },\n): string {\n const shouldFlatten = opts?.flatten !== false;\n return source.replace(\n /(['\"])@\\/([a-z][a-z0-9-]*)(\\/[^'\"]*)?\\1/g,\n (full, quote: string, root: string, rest: string | undefined) => {\n const aliasKey = SOURCE_ROOT_TO_ALIAS_KEY[root];\n if (!aliasKey) return full;\n const alias = aliases[aliasKey];\n const normalized = aliasToImportPath(alias);\n const resolvedRest = shouldFlatten ? flattenRestPath(rest) : (rest ?? '');\n return `${quote}${normalized}${resolvedRest}${quote}`;\n },\n );\n}\n\n/**\n * Flatten a source-tree relative path for the installed (flat) layout.\n *\n * In the UI source tree, files live in per-entry directories:\n * `@/components/skeleton/skeleton` → rest = `/skeleton/skeleton`\n * After install, they are placed flat in the alias directory:\n * `@/components/ui/skeleton` → rest = `/skeleton`\n *\n * When rest has exactly two path segments (`/dir/file`), the first segment\n * (the entry directory) is stripped, leaving only the file reference.\n * Single-segment paths (e.g. `/cn`) pass through unchanged.\n */\nfunction flattenRestPath(rest: string | undefined): string {\n if (!rest) return '';\n // Split: \"/skeleton/skeleton\" → [\"\", \"skeleton\", \"skeleton\"]\n const segments = rest.split('/');\n if (segments.length === 3) {\n // Two real segments: /dir/file → /file\n return `/${segments[2]}`;\n }\n return rest;\n}\n\n/**\n * Convert an alias path (relative to the project root, e.g. `src/lib/utils`)\n * into an import-path prefix (`@/lib/utils`).\n *\n * Strips a leading `src/` so the path matches the convention of a `@/*` →\n * `src/*` tsconfig mapping. If the alias has a different prefix (for projects\n * that don't put code under `src/`), we keep it verbatim with `@/` prepended.\n */\nfunction aliasToImportPath(alias: string): string {\n const trimmed = alias.replace(/^\\.\\//, '').replace(/\\/$/, '');\n if (trimmed.startsWith('src/')) {\n return `@/${trimmed.slice('src/'.length)}`;\n }\n return `@/${trimmed}`;\n}\n","import type {\n InstalledManifest,\n InstalledResource,\n} from '@teamix-evo/registry';\nimport { loadUiData } from './ui-client.js';\nimport { installUiEntries } from './ui-installer.js';\nimport {\n readProjectConfig,\n writeProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\n\nconst DEFAULT_UI_PACKAGE = '@teamix-evo/ui';\n\nexport interface RunUiAddOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Entry ids to install (registry dependencies are resolved transitively). */\n ids: string[];\n /** When true, overwrite frozen entries that already exist on disk. */\n overwrite?: boolean;\n /** Override the ui package name (defaults to \"@teamix-evo/ui\"). */\n packageName?: string;\n /**\n * When true, allow installing entries that live in `manifest.deprecatedEntries`\n * (ADR 0028). Default: false — deprecated ids are treated as unknown and the\n * call errors with a hint pointing the user at the active replacement.\n */\n includeDeprecated?: boolean;\n}\n\nexport interface RunUiAddResult {\n packageName: string;\n /** Registered ids in install order (deps + requested). */\n orderedIds: string[];\n /** Number of files written. */\n written: number;\n /** Number of files skipped due to frozen + exists. */\n skipped: number;\n /** Aggregate npm dependencies of the installed entries. */\n npmDependencies: Record<string, string>;\n /** Per-file install records merged into the installed manifest. */\n resources: InstalledResource[];\n}\n\n/**\n * Programmatic equivalent of `teamix-evo ui add <ids...>`.\n *\n * Requires `packages.ui` to already exist in `.teamix-evo/config.json`\n * (i.e. {@link runUiInit} was called earlier).\n */\nexport async function runUiAdd(\n options: RunUiAddOptions,\n): Promise<RunUiAddResult> {\n const { projectRoot, ids, overwrite, includeDeprecated } = options;\n const packageName = options.packageName ?? DEFAULT_UI_PACKAGE;\n\n if (ids.length === 0) {\n throw new Error('At least one entry id must be provided.');\n }\n\n const config = await readProjectConfig(projectRoot);\n const uiCfg = config?.packages?.ui;\n if (!config || !uiCfg?.aliases) {\n throw new Error(\n 'UI not initialized. Run `runUiInit` (or `teamix-evo ui init`) first.',\n );\n }\n\n const { manifest, packageRoot } = await loadUiData(packageName);\n\n // Per ADR 0028: deprecated entries are archived in `deprecatedEntries`\n // and not exposed by default. When the caller opts in, we splice them\n // back into the active list so dependency resolution and install work\n // exactly as for active entries.\n const archived = manifest.deprecatedEntries ?? [];\n const archivedIds = new Set(archived.map((e) => e.id));\n const activeIds = new Set(manifest.entries.map((e) => e.id));\n\n const requestedDeprecated = ids.filter((id) => archivedIds.has(id));\n if (requestedDeprecated.length > 0 && !includeDeprecated) {\n const list = requestedDeprecated.map((s) => `\"${s}\"`).join(', ');\n throw new Error(\n `Refusing to install deprecated entr${\n requestedDeprecated.length === 1 ? 'y' : 'ies'\n } ${list}. ` +\n 'These entries are archived and not part of the active distribution (ADR 0028). ' +\n 'Pass `--include-deprecated` to override (e.g. for migration tooling).',\n );\n }\n\n const effectiveManifest = includeDeprecated\n ? { ...manifest, entries: [...manifest.entries, ...archived] }\n : manifest;\n\n const knownIds = new Set([\n ...activeIds,\n ...(includeDeprecated ? archivedIds : []),\n ]);\n const unknown = ids.filter((id) => !knownIds.has(id));\n if (unknown.length > 0) {\n throw new Error(\n `Unknown entry id(s): ${unknown\n .map((s) => `\"${s}\"`)\n .join(', ')}. Run \\`teamix-evo ui list\\` to see options.`,\n );\n }\n\n const result = await installUiEntries({\n projectRoot,\n manifest: effectiveManifest,\n packageRoot,\n aliases: uiCfg.aliases,\n requested: ids,\n skipExisting: !overwrite,\n });\n\n const installed: InstalledManifest = (await readInstalledManifest(\n projectRoot,\n )) ?? { schemaVersion: 1, installed: [] };\n\n const idx = installed.installed.findIndex((p) => p.package === packageName);\n const prior = idx >= 0 ? installed.installed[idx] : null;\n const mergedResources = mergeResources(\n prior?.resources ?? [],\n result.resources,\n );\n\n const entry = {\n package: packageName,\n variant: '_flat',\n version: manifest.version,\n installedAt: new Date().toISOString(),\n resources: mergedResources,\n };\n if (idx >= 0) installed.installed[idx] = entry;\n else installed.installed.push(entry);\n await writeInstalledManifest(projectRoot, installed);\n\n if (uiCfg.version !== manifest.version) {\n uiCfg.version = manifest.version;\n await writeProjectConfig(projectRoot, config);\n }\n\n return {\n packageName,\n orderedIds: result.orderedIds,\n written: result.written,\n skipped: result.skipped,\n npmDependencies: result.npmDependencies,\n resources: result.resources,\n };\n}\n\nfunction mergeResources<T extends { id: string }>(prior: T[], next: T[]): T[] {\n const merged = new Map<string, T>();\n for (const r of prior) merged.set(r.id, r);\n for (const r of next) merged.set(r.id, r);\n return Array.from(merged.values());\n}\n","import type { UiEntry } from '@teamix-evo/registry';\nimport { loadUiData } from './ui-client.js';\nimport { readInstalledManifest } from './state.js';\n\nconst DEFAULT_UI_PACKAGE = '@teamix-evo/ui';\n\nexport interface RunUiListOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** When true, only return entries that are already installed. */\n installedOnly?: boolean;\n /** Override the ui package name (defaults to \"@teamix-evo/ui\"). */\n packageName?: string;\n /**\n * When true, also include archived entries from `manifest.deprecatedEntries`\n * (ADR 0028). They are flagged with `deprecated: true` in the result.\n */\n includeDeprecated?: boolean;\n}\n\nexport interface UiEntryListItem {\n id: string;\n type: UiEntry['type'];\n description: string;\n installed: boolean;\n /** True when the entry comes from `manifest.deprecatedEntries` (ADR 0028). */\n deprecated: boolean;\n}\n\nexport interface RunUiListResult {\n packageName: string;\n /** Total number of entries declared by the package manifest. */\n total: number;\n /** Number of installed entries (based on the project's installed manifest). */\n installedCount: number;\n /** Filtered + decorated entries. */\n entries: UiEntryListItem[];\n}\n\n/**\n * Programmatic equivalent of `teamix-evo ui list`.\n *\n * Returns structured data; the CLI command formats it for terminal output.\n */\nexport async function runUiList(\n options: RunUiListOptions,\n): Promise<RunUiListResult> {\n const { projectRoot, installedOnly, includeDeprecated } = options;\n const packageName = options.packageName ?? DEFAULT_UI_PACKAGE;\n\n const { manifest } = await loadUiData(packageName);\n const installedManifest = await readInstalledManifest(projectRoot);\n\n const installedIds = new Set<string>();\n const uiPkg = installedManifest?.installed.find(\n (p) => p.package === packageName,\n );\n for (const r of uiPkg?.resources ?? []) {\n const colon = r.id.indexOf(':');\n installedIds.add(colon >= 0 ? r.id.slice(0, colon) : r.id);\n }\n\n const archived = manifest.deprecatedEntries ?? [];\n const pool = includeDeprecated\n ? [\n ...manifest.entries.map((e) => ({ entry: e, deprecated: false })),\n ...archived.map((e) => ({ entry: e, deprecated: true })),\n ]\n : manifest.entries.map((e) => ({ entry: e, deprecated: false }));\n\n const entries: UiEntryListItem[] = pool\n .filter(({ entry }) => !installedOnly || installedIds.has(entry.id))\n .map(({ entry, deprecated }) => ({\n id: entry.id,\n type: entry.type,\n description: entry.description,\n installed: installedIds.has(entry.id),\n deprecated,\n }));\n\n return {\n packageName,\n total: manifest.entries.length + (includeDeprecated ? archived.length : 0),\n installedCount: installedIds.size,\n entries,\n };\n}\n","/**\n * Programmatic install for variant-aware UI packages — biz-ui & templates.\n *\n * Per [ADR 0014](../../../../docs/adr/0014-ui-biz-ui-templates-tier.md), these\n * two packages share the variant-aware shape: top-level catalog + per-variant\n * manifest. The install logic is the same as `runUiAdd` (registry dependency\n * resolution + frozen-on-add + import rewrite) — only differences are:\n *\n * 1. The package source is `<pkg>/variants/<variant>/` rather than `<pkg>/`\n * 2. A `--variant` selector picks which variant to install from\n * 3. The installed manifest entry records `variant: \"<name>\"` rather than\n * `_flat`\n *\n * This module exposes a single shared implementation parametrized by\n * `packageName` (`@teamix-evo/biz-ui` or `@teamix-evo/templates`) and is\n * surfaced via `runBizUiAdd` / `runTemplatesAdd` thin wrappers.\n */\nimport * as path from 'node:path';\nimport { createRequire } from 'node:module';\nimport type {\n InstalledManifest,\n InstalledResource,\n UiEntry,\n UiPackageManifest,\n VariantUiPackageName,\n} from '@teamix-evo/registry';\nimport {\n loadUiPackageManifest,\n loadVariantUiPackageCatalog,\n loadVariantUiPackageManifest,\n} from '@teamix-evo/registry';\nimport { installUiEntries } from './ui-installer.js';\nimport {\n readProjectConfig,\n readInstalledManifest,\n writeInstalledManifest,\n} from './state.js';\n\nconst require = createRequire(import.meta.url);\n\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\nexport interface RunVariantUiAddOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /** Variant id (e.g. `\"opentrek\"`). */\n variant: string;\n /** Entry ids to install. */\n ids: string[];\n /** When true, overwrite frozen entries that already exist on disk. */\n overwrite?: boolean;\n /** Override the package name. */\n packageName?: string;\n /**\n * Override resolution of the package root. When set, skips\n * `require.resolve(\"<packageName>/package.json\")`.\n */\n packageRoot?: string;\n}\n\nexport interface RunVariantUiAddResult {\n packageName: string;\n variant: string;\n orderedIds: string[];\n written: number;\n skipped: number;\n npmDependencies: Record<string, string>;\n resources: InstalledResource[];\n}\n\nasync function runVariantUiAdd(\n packageName: VariantUiPackageName,\n options: RunVariantUiAddOptions,\n): Promise<RunVariantUiAddResult> {\n const { projectRoot, variant, ids, overwrite } = options;\n const fullPackageName = options.packageName ?? `@teamix-evo/${packageName}`;\n\n if (ids.length === 0) {\n throw new Error('At least one entry id must be provided.');\n }\n\n const config = await readProjectConfig(projectRoot);\n const uiCfg = config?.packages?.ui;\n if (!config || !uiCfg?.aliases) {\n throw new Error(\n `UI not initialized. Run \\`teamix-evo ui init\\` first — \\`${packageName} add\\` writes into the same alias map (business / templates).`,\n );\n }\n\n const packageRoot =\n options.packageRoot ?? resolvePackageRoot(fullPackageName);\n\n // Validate that this variant exists in the catalog (clear error if not).\n const catalog = await loadVariantUiPackageCatalog(packageRoot);\n if (!catalog.variants.some((v) => v.name === variant)) {\n const known = catalog.variants.map((v) => v.name).join(', ');\n throw new Error(\n `Variant \"${variant}\" not found in ${fullPackageName}. Known variants: ${known}. Hint: \\`teamix-evo ${packageName} list-variants\\` shows all.`,\n );\n }\n\n // Load the per-variant manifest from packages/<pkg>/variants/<variant>/.\n const variantDir = path.join(packageRoot, 'variants', variant);\n const variantManifest = await loadVariantUiPackageManifest(variantDir);\n\n // Validate requested ids (must be defined in this variant package, not in ui)\n const knownIds = new Set(variantManifest.entries.map((e) => e.id));\n const unknown = ids.filter((id) => !knownIds.has(id));\n if (unknown.length > 0) {\n throw new Error(\n `Unknown entry id(s) in ${packageName}#${variant}: ${unknown\n .map((s) => `\"${s}\"`)\n .join(', ')}. Run \\`teamix-evo ${packageName} list-variants\\` to see this package's variants, or \\`teamix-evo ${packageName} list --variant ${variant}\\` for its entries.`,\n );\n }\n\n // Cross-package dependency resolution (fixes #22).\n // variant-aware entries (biz-ui / templates) reference @teamix-evo/ui entries\n // by id via `registryDependencies` (e.g. tenant-switcher → popover/button/cn).\n // Merge ui package's entries into the dep graph so the resolver can find\n // them. The installer's skipExisting=frozen guard means already-installed ui\n // entries are not rewritten.\n const uiPackageRoot = resolvePackageRoot('@teamix-evo/ui');\n const uiManifest = await loadUiPackageManifest(uiPackageRoot);\n\n // Resolve each entry's true package root for source file paths. Entries from\n // the variant package live under variantDir; entries from @teamix-evo/ui live\n // under uiPackageRoot.\n const entryPackageRoot = new Map<string, string>();\n const mergedEntries: UiEntry[] = [];\n for (const e of variantManifest.entries) {\n entryPackageRoot.set(e.id, variantDir);\n mergedEntries.push(e);\n }\n for (const e of uiManifest.entries) {\n // variant entry id wins over ui entry of same id (rare/illegal but safe).\n if (entryPackageRoot.has(e.id)) continue;\n entryPackageRoot.set(e.id, uiPackageRoot);\n mergedEntries.push(e);\n }\n\n const adaptedManifest: UiPackageManifest = {\n schemaVersion: 1,\n package: 'ui',\n version: variantManifest.version,\n engines: variantManifest.engines,\n entries: mergedEntries,\n };\n\n const result = await installUiEntries({\n projectRoot,\n manifest: adaptedManifest,\n packageRoot: variantDir, // default for variant entries\n entryPackageRoot, // ui entries resolve from uiPackageRoot\n aliases: uiCfg.aliases,\n requested: ids,\n skipExisting: !overwrite,\n });\n\n // Update installed manifest, keyed by (package, variant). Multiple variants\n // of the same package can co-exist (rare but legal).\n const installed: InstalledManifest = (await readInstalledManifest(\n projectRoot,\n )) ?? { schemaVersion: 1, installed: [] };\n\n const idx = installed.installed.findIndex(\n (p) => p.package === fullPackageName && p.variant === variant,\n );\n const prior = idx >= 0 ? installed.installed[idx] : null;\n const mergedResources = mergeResources(\n prior?.resources ?? [],\n result.resources,\n );\n\n const entry = {\n package: fullPackageName,\n variant,\n version: variantManifest.version,\n installedAt: new Date().toISOString(),\n resources: mergedResources,\n };\n if (idx >= 0) installed.installed[idx] = entry;\n else installed.installed.push(entry);\n await writeInstalledManifest(projectRoot, installed);\n\n return {\n packageName: fullPackageName,\n variant,\n orderedIds: result.orderedIds,\n written: result.written,\n skipped: result.skipped,\n npmDependencies: result.npmDependencies,\n resources: result.resources,\n };\n}\n\nfunction mergeResources<T extends { id: string }>(prior: T[], next: T[]): T[] {\n const merged = new Map<string, T>();\n for (const r of prior) merged.set(r.id, r);\n for (const r of next) merged.set(r.id, r);\n return Array.from(merged.values());\n}\n\n/** `teamix-evo biz-ui add <ids...> --variant <name>`. */\nexport async function runBizUiAdd(\n options: RunVariantUiAddOptions,\n): Promise<RunVariantUiAddResult> {\n return runVariantUiAdd('biz-ui', options);\n}\n\n/** `teamix-evo templates add <ids...> --variant <name>`. */\nexport async function runTemplatesAdd(\n options: RunVariantUiAddOptions,\n): Promise<RunVariantUiAddResult> {\n return runVariantUiAdd('templates', options);\n}\n\n// ─── List variants ───────────────────────────────────────────────────────────\n\nexport interface ListVariantUiResult {\n packageName: string;\n variants: Array<{\n name: string;\n displayName: string;\n version: string;\n description?: string;\n }>;\n}\n\nasync function listVariantUi(\n packageName: VariantUiPackageName,\n packageRoot?: string,\n): Promise<ListVariantUiResult> {\n const fullPackageName = `@teamix-evo/${packageName}`;\n const root = packageRoot ?? resolvePackageRoot(fullPackageName);\n const catalog = await loadVariantUiPackageCatalog(root);\n return {\n packageName: fullPackageName,\n variants: catalog.variants.map((v) => ({\n name: v.name,\n displayName: v.displayName,\n version: v.version,\n description: v.description,\n })),\n };\n}\n\nexport async function listBizUiVariants(\n packageRoot?: string,\n): Promise<ListVariantUiResult> {\n return listVariantUi('biz-ui', packageRoot);\n}\n\nexport async function listTemplatesVariants(\n packageRoot?: string,\n): Promise<ListVariantUiResult> {\n return listVariantUi('templates', packageRoot);\n}\n\n// ─── List entries inside a variant ───────────────────────────────────────────\n\nexport interface ListVariantUiEntriesResult {\n packageName: string;\n variant: string;\n entries: Array<{\n id: string;\n name: string;\n type: string;\n description?: string;\n registryDependencies: string[];\n }>;\n}\n\nasync function listVariantUiEntries(\n packageName: VariantUiPackageName,\n variant: string,\n packageRoot?: string,\n): Promise<ListVariantUiEntriesResult> {\n const fullPackageName = `@teamix-evo/${packageName}`;\n const root = packageRoot ?? resolvePackageRoot(fullPackageName);\n const catalog = await loadVariantUiPackageCatalog(root);\n if (!catalog.variants.some((v) => v.name === variant)) {\n const known = catalog.variants.map((v) => v.name).join(', ');\n throw new Error(\n `Variant \"${variant}\" not found in ${fullPackageName}. Known: ${known}.`,\n );\n }\n const variantDir = path.join(root, 'variants', variant);\n const variantManifest = await loadVariantUiPackageManifest(variantDir);\n return {\n packageName: fullPackageName,\n variant,\n entries: variantManifest.entries.map((e) => ({\n id: e.id,\n name: e.name,\n type: e.type,\n description: e.description,\n registryDependencies: e.registryDependencies ?? [],\n })),\n };\n}\n\nexport async function listBizUiEntries(\n variant: string,\n packageRoot?: string,\n): Promise<ListVariantUiEntriesResult> {\n return listVariantUiEntries('biz-ui', variant, packageRoot);\n}\n\nexport async function listTemplatesEntries(\n variant: string,\n packageRoot?: string,\n): Promise<ListVariantUiEntriesResult> {\n return listVariantUiEntries('templates', variant, packageRoot);\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs';\nimport { execa } from 'execa';\nimport {\n backupFile,\n fileExists,\n readFileOrNull,\n writeFileSafe,\n} from '../utils/fs.js';\nimport { logger } from '../utils/logger.js';\n\n// ─── Config file content ─────────────────────────────────────────────────────\n\nconst ESLINT_CONFIG_CONTENT = `/**\n * teamix-evo consumer ESLint preset — 9 token-discipline rules.\n * - Repo-wide: no-color-literal / no-arbitrary-tw-value / no-raw-color-scale /\n * no-large-radius / prefer-gap-over-space / no-manual-dark-classnames /\n * dialog-must-have-title (all error)\n * - src/components/ui/** only: no-relative-ui-import / icon-from-lucide (error)\n *\n * See ADR 0008 / docs/principles.md §P4.\n */\nimport consumerPreset from '@teamix-evo/eslint-config/presets/consumer';\n\nexport default [...consumerPreset];\n`;\n\nconst STYLELINT_CONFIG_CONTENT = `/** @type {import('stylelint').Config} */\nmodule.exports = {\n extends: ['@teamix-evo/stylelint-config/presets/consumer'],\n};\n`;\n\n// ─── Types ───────────────────────────────────────────────────────────────────\n\n/**\n * Phase 3.E lint conflict strategies (mirrors `init-conflicts.ts`).\n *\n * `merge` and `backup-overwrite` both back up the existing user file before\n * writing the teamix-evo template; `merge` additionally surfaces an AI-assist\n * hint so the manage / code skill can guide the user through merging custom\n * rules. `skip` keeps the user's file as-is and emits no template.\n */\nexport type LintConflictStrategy =\n | 'merge'\n | 'backup-overwrite'\n | 'skip'\n | 'overwrite';\n\nexport interface RunLintInitOptions {\n /** Absolute project root directory. */\n projectRoot: string;\n /**\n * Skip npm dependency installation. Used by the create scaffold where\n * dependencies are already declared in the template package.json and\n * installed in a later batch step.\n */\n skipInstall?: boolean;\n /**\n * Phase 3.E: strategy for handling existing ESLint config files.\n * Defaults to `'overwrite'` (legacy behaviour); the `init` orchestrator\n * passes the wizard-resolved value when consumer files are detected.\n */\n eslintStrategy?: LintConflictStrategy;\n /**\n * Phase 3.E: strategy for handling existing Stylelint config files.\n */\n stylelintStrategy?: LintConflictStrategy;\n /**\n * Phase 3.E: paths of existing ESLint configs (relative to projectRoot)\n * to back up. Empty when no consumer config was detected.\n */\n eslintExistingPaths?: string[];\n /**\n * Phase 3.E: paths of existing Stylelint configs (relative to projectRoot).\n */\n stylelintExistingPaths?: string[];\n}\n\nexport type RunLintInitResult =\n | {\n status: 'installed';\n eslint: boolean;\n stylelint: boolean;\n /** True when the user had a custom config and asked for AI-assisted merge. */\n eslintMergeRequested?: boolean;\n stylelintMergeRequested?: boolean;\n /** True when the strategy asked us to keep the user file untouched. */\n eslintSkipped?: boolean;\n stylelintSkipped?: boolean;\n /**\n * True when `package.json` was actually patched (lint / lint:css\n * scripts inserted). Powers the project-init change ledger so the\n * CLI does not report a phantom write when both scripts already\n * existed.\n */\n packageJsonPatched?: boolean;\n /**\n * True when the consumer's existing stylelint config was kept (skip /\n * merge) and does not extend a teamix-evo preset — token definition\n * files may trigger false-positive lint errors without `ignoreFiles`.\n */\n stylelintIgnoreFilesWarning?: boolean;\n }\n | {\n status: 'already-initialized';\n };\n\n// ─── Lint dependencies ───────────────────────────────────────────────────────\n\nconst ESLINT_DEPS = [\n '@teamix-evo/eslint-config',\n 'eslint',\n '@typescript-eslint/parser',\n];\n\nconst STYLELINT_DEPS = ['@teamix-evo/stylelint-config', 'stylelint'];\n\n// ─── Implementation ──────────────────────────────────────────────────────────\n\n/**\n * Programmatic equivalent of `teamix-evo lint init`.\n *\n * Writes lint configuration files and optionally installs dependencies.\n * Idempotent: if both config files already exist, returns `already-initialized`.\n */\nexport async function runLintInit(\n options: RunLintInitOptions,\n): Promise<RunLintInitResult> {\n const {\n projectRoot,\n skipInstall,\n eslintStrategy = 'overwrite',\n stylelintStrategy = 'overwrite',\n eslintExistingPaths = [],\n stylelintExistingPaths = [],\n } = options;\n\n const eslintConfigPath = path.join(projectRoot, 'eslint.config.js');\n const stylelintConfigPath = path.join(projectRoot, 'stylelint.config.cjs');\n\n const eslintTemplateExists = await fileExists(eslintConfigPath);\n const stylelintTemplateExists = await fileExists(stylelintConfigPath);\n\n // Phase 3.E: a `skip` strategy only short-circuits when the *consumer*\n // already has a config. Without it we still need to write our template.\n const eslintSkipRequested =\n eslintStrategy === 'skip' && eslintExistingPaths.length > 0;\n const stylelintSkipRequested =\n stylelintStrategy === 'skip' && stylelintExistingPaths.length > 0;\n\n const eslintNeedsWrite = !eslintTemplateExists && !eslintSkipRequested;\n const stylelintNeedsWrite =\n !stylelintTemplateExists && !stylelintSkipRequested;\n\n if (!eslintNeedsWrite && !stylelintNeedsWrite) {\n return { status: 'already-initialized' };\n }\n\n // ─── Install dependencies ──────────────────────────────────────────────\n if (!skipInstall) {\n const depsToInstall = [\n ...(eslintNeedsWrite ? ESLINT_DEPS : []),\n ...(stylelintNeedsWrite ? STYLELINT_DEPS : []),\n ];\n\n if (depsToInstall.length > 0) {\n const pm = detectPm(projectRoot);\n const args =\n pm === 'yarn'\n ? ['add', '--dev', ...depsToInstall]\n : pm === 'pnpm'\n ? ['add', '-D', ...depsToInstall]\n : ['install', '--save-dev', ...depsToInstall];\n\n logger.info(`Installing lint deps via ${pm}...`);\n await execa(pm, args, { cwd: projectRoot, stdio: 'inherit' });\n }\n }\n\n // ─── Phase 3.E: back up consumer configs before writing template ───────\n // Phase 1.A2 — `overwrite` strategy still demands a `.bak` so the user\n // can recover the original file. Only `eslintNeedsWrite` /\n // `stylelintNeedsWrite` gates the operation (a `skip`d file is left\n // untouched, so no backup is needed).\n if (eslintNeedsWrite && eslintExistingPaths.length > 0) {\n for (const rel of eslintExistingPaths) {\n await backupFile(path.join(projectRoot, rel), projectRoot);\n }\n }\n if (stylelintNeedsWrite && stylelintExistingPaths.length > 0) {\n for (const rel of stylelintExistingPaths) {\n await backupFile(path.join(projectRoot, rel), projectRoot);\n }\n }\n\n // ─── Write config files ────────────────────────────────────────────────\n let wroteEslint = false;\n let wroteStylelint = false;\n\n if (eslintNeedsWrite) {\n await writeFileSafe(eslintConfigPath, ESLINT_CONFIG_CONTENT);\n logger.debug(`Wrote eslint.config.js → ${eslintConfigPath}`);\n wroteEslint = true;\n }\n\n if (stylelintNeedsWrite) {\n await writeFileSafe(stylelintConfigPath, STYLELINT_CONFIG_CONTENT);\n logger.debug(`Wrote stylelint.config.cjs → ${stylelintConfigPath}`);\n wroteStylelint = true;\n }\n\n // ─── Patch package.json scripts ────────────────────────────────────────\n // Phase 1.A2: package.json is a high-value user file — back it up before\n // we mutate `scripts.lint` / `scripts['lint:css']` so the user can revert\n // the patch without git if needed.\n const packageJsonPatched = await patchPackageJsonScripts(projectRoot);\n\n // ─── Phase 2.3: detect missing ignoreFiles for token files ────────────\n // When the consumer keeps their own stylelint config (skip / merge), check\n // whether it extends a teamix-evo preset. If not, token definition files\n // (tokens.theme.css, tokens.overrides.css) will trigger false-positive\n // no-color-literal / no-hardcoded-dimension errors. Print a non-invasive\n // warning with the recommended fix (review safety-net: never auto-modify).\n let stylelintIgnoreFilesWarning = false;\n if (!stylelintNeedsWrite && stylelintTemplateExists) {\n try {\n const existingContent = fs.readFileSync(stylelintConfigPath, 'utf-8');\n const usesTeamixPreset =\n existingContent.includes('@teamix-evo/stylelint-config/presets/') ||\n existingContent.includes('@teamix-evo/stylelint-config/preset/');\n const hasTokenIgnore =\n existingContent.includes('tokens.theme.css') &&\n existingContent.includes('tokens.overrides.css');\n if (!usesTeamixPreset && !hasTokenIgnore) {\n stylelintIgnoreFilesWarning = true;\n logger.warn(\n [\n '检测到现有 stylelint 配置未排除 token 定义文件。',\n '建议在 stylelint.config.cjs 中添加 ignoreFiles:',\n '',\n ' ignoreFiles: [',\n \" '**/tokens.theme.css',\",\n \" '**/tokens.overrides.css',\",\n ' ]',\n '',\n '或切换到 teamix-evo 预设以自动获得排除规则:',\n '',\n \" extends: ['@teamix-evo/stylelint-config/presets/consumer']\",\n ].join('\\n'),\n );\n }\n } catch {\n // best-effort — config may not be a readable text file\n }\n }\n\n return {\n status: 'installed',\n eslint: wroteEslint,\n stylelint: wroteStylelint,\n eslintMergeRequested:\n wroteEslint &&\n eslintStrategy === 'merge' &&\n eslintExistingPaths.length > 0,\n stylelintMergeRequested:\n wroteStylelint &&\n stylelintStrategy === 'merge' &&\n stylelintExistingPaths.length > 0,\n eslintSkipped: eslintSkipRequested,\n stylelintSkipped: stylelintSkipRequested,\n packageJsonPatched,\n stylelintIgnoreFilesWarning,\n };\n}\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\n/**\n * Detect package manager from lockfile presence.\n */\nfunction detectPm(projectRoot: string): 'pnpm' | 'yarn' | 'npm' {\n if (fs.existsSync(path.join(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm';\n if (fs.existsSync(path.join(projectRoot, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\n/**\n * Add lint scripts to package.json if they don't already exist.\n *\n * Returns `true` when at least one of `scripts.lint` / `scripts['lint:css']`\n * was inserted (so the caller can decide whether to surface a `package.json`\n * change in the project-init ledger). Returns `false` when both scripts\n * already existed or when `package.json` is missing/unparseable.\n */\nasync function patchPackageJsonScripts(projectRoot: string): Promise<boolean> {\n const pkgPath = path.join(projectRoot, 'package.json');\n const raw = await readFileOrNull(pkgPath);\n if (!raw) return false;\n\n let pkg: Record<string, unknown>;\n try {\n pkg = JSON.parse(raw);\n } catch {\n return false;\n }\n\n const scripts = (pkg.scripts ?? {}) as Record<string, string>;\n let changed = false;\n\n if (!scripts.lint) {\n scripts.lint = 'eslint src/';\n changed = true;\n }\n if (!scripts['lint:css']) {\n scripts['lint:css'] = \"stylelint 'src/**/*.css'\";\n changed = true;\n }\n\n if (changed) {\n // Backup user package.json before patching scripts (Phase 1.A2).\n await backupFile(pkgPath, projectRoot);\n pkg.scripts = scripts;\n await writeFileSafe(pkgPath, JSON.stringify(pkg, null, 2) + '\\n');\n logger.debug('Patched package.json scripts with lint / lint:css');\n }\n return changed;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { hasManagedRegion, replaceManagedRegion } from '@teamix-evo/registry';\nimport { backupFile, fileExists, readFileOrNull } from '../utils/fs.js';\nimport { getSkillsSourceDir } from './state.js';\n\n/**\n * Generate `<projectRoot>/AGENTS.md` as a skill-trigger fallback (ADR 0038).\n *\n * The file is **regenerable**: it consolidates TRIGGER / SKIP excerpts from\n * each installed SKILL.md frontmatter description into one terse index, so\n * AGENTS.md-aware IDEs (Codex / Cursor / Claude Code / Qoder) preheat the\n * skill activation conditions even when the user prompt does not directly\n * hit the description-based trigger.\n *\n * Out of scope (per ADR 0038):\n * - Does NOT copy skill body / rules / patterns — those stay in the skill.\n * - Does NOT include `teamix-evo-manage` (entry skill, global scope, ADR 0033).\n *\n * Lifted from `create-teamix-evo` (v0.5) into `teamix-evo/core` so both\n * `npm create teamix-evo` (scaffold path) and `teamix-evo init` (existing-\n * project path, ADR 0019 task #5) emit identical AGENTS.md output.\n *\n * @module teamix-evo/core/agents-md\n */\n\nexport interface RunGenerateAgentsMdOptions {\n /** Absolute path to the consumer project root. */\n projectRoot: string;\n /** Tokens / skills variant (e.g. \"opentrek\"). Used for header context. */\n variant: string;\n /**\n * Skill ids whose `<projectRoot>/.teamix-evo/skills/<id>/SKILL.md` should be\n * indexed. Caller is responsible for filtering out global-only skills\n * (e.g. `teamix-evo-manage`).\n */\n skillIds: string[];\n /**\n * Reconciliation mode (Phase 2.B):\n * - `'overwrite'` (default): always rewrite the full file. Pre-existing\n * content is backed up and discarded.\n * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed\n * region. When the consumer file lacks the region, prepend a fresh\n * managed block ahead of the user's content (auto-adopt). The user's\n * non-managed sections are preserved.\n *\n * In both modes, an existing file is backed up under\n * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before any mutation.\n */\n mode?: 'overwrite' | 'merge-managed';\n}\n\nexport interface RunGenerateAgentsMdResult {\n /** Absolute path of the written `AGENTS.md`. */\n path: string;\n /** Number of skill sections rendered (missing SKILL.md degradations are still counted). */\n skillCount: number;\n /** Skill ids whose SKILL.md could not be read (rendered as degraded section). */\n missingSkillIds: string[];\n /**\n * True when an existing AGENTS.md was backed up under\n * `.teamix-evo/.backups/AGENTS.md.<isoTs>.bak` before being overwritten\n * (Phase 1.A2 — full backup strategy).\n */\n backedUp: boolean;\n /**\n * Outcome of the merge step (Phase 2.B):\n * - `'created'`: no AGENTS.md existed; wrote a fresh full template.\n * - `'overwritten'`: existed but mode='overwrite' — full rewrite.\n * - `'managed-replaced'`: mode='merge-managed' and the consumer file\n * already had the `teamix-evo-skills` managed region; only that region\n * was rewritten. User content outside is preserved.\n * - `'managed-prepended'`: mode='merge-managed' but the consumer file\n * did not yet have the managed region; a fresh block was inserted at\n * the top, with the existing user content kept below.\n */\n merge: 'created' | 'overwritten' | 'managed-replaced' | 'managed-prepended';\n}\n\n/** Region id wrapping the auto-generated skill index. */\nexport const AGENTS_MD_MANAGED_ID = 'teamix-evo-skills';\n\ninterface SkillDescriptionParts {\n /** First non-empty line(s) of `description` (the capability statement). */\n capability: string;\n trigger: string | null;\n skip: string | null;\n coordinates: string | null;\n}\n\n/**\n * Generate and write the `AGENTS.md` file.\n *\n * Phase 2.B — reconciliation modes:\n * - `'overwrite'` (default): regenerable behaviour, full rewrite.\n * - `'merge-managed'`: rewrite only the `teamix-evo-skills` managed region\n * so user-authored sections (project-specific guidance, design tokens,\n * prompts) are never clobbered.\n *\n * Existing files are always backed up under `.teamix-evo/.backups/` before\n * mutation (ADR 0019 §2, Phase 1.A2).\n */\nexport async function runGenerateAgentsMd(\n options: RunGenerateAgentsMdOptions,\n): Promise<RunGenerateAgentsMdResult> {\n const { projectRoot, variant, skillIds } = options;\n const mode = options.mode ?? 'overwrite';\n\n // Stable order: design → code → others (alphabetical within each bucket).\n const ordered = [...skillIds].sort(\n (a, b) => bucketRank(a) - bucketRank(b) || a.localeCompare(b),\n );\n\n const sections: string[] = [];\n const missingSkillIds: string[] = [];\n for (const id of ordered) {\n const { section, missing } = await renderSkillSection(projectRoot, id);\n sections.push(section);\n if (missing) missingSkillIds.push(id);\n }\n\n const target = path.join(projectRoot, 'AGENTS.md');\n const targetExists = await fileExists(target);\n const fullTemplate = renderAgentsMd({ variant, sections });\n const managedBody = renderManagedBlockBody({ variant, sections });\n\n let outputContent: string;\n let merge: RunGenerateAgentsMdResult['merge'];\n\n if (!targetExists) {\n outputContent = fullTemplate;\n merge = 'created';\n } else {\n // Backup before any mutation — truthful even if downstream throws.\n await backupFile(target, projectRoot);\n if (mode === 'merge-managed') {\n const existing = (await readFileOrNull(target)) ?? '';\n if (hasManagedRegion(existing, AGENTS_MD_MANAGED_ID)) {\n outputContent = replaceManagedRegion(\n existing,\n AGENTS_MD_MANAGED_ID,\n managedBody,\n );\n merge = 'managed-replaced';\n } else {\n // Auto-adopt: place the managed block at the top so AGENTS.md-aware\n // IDEs preheat skill triggers first, then keep the user's prior\n // content as a non-managed tail. A trailing precedence notice goes\n // immediately after the managed block.\n const wrapped = wrapManagedBlock(managedBody);\n outputContent = `${wrapped}\\n\\n${PRECEDENCE_NOTICE}\\n\\n${existing.trimStart()}`;\n merge = 'managed-prepended';\n }\n } else {\n // overwrite — historical default.\n outputContent = fullTemplate;\n merge = 'overwritten';\n }\n }\n\n await fs.writeFile(target, outputContent, 'utf8');\n return {\n path: target,\n skillCount: ordered.length,\n missingSkillIds,\n backedUp: targetExists,\n merge,\n };\n}\n\nfunction bucketRank(id: string): number {\n if (id.startsWith('teamix-evo-design-')) return 0;\n if (id.startsWith('teamix-evo-code-')) return 1;\n return 2;\n}\n\nasync function renderSkillSection(\n projectRoot: string,\n skillId: string,\n): Promise<{ section: string; missing: boolean }> {\n const skillPath = path.join(\n getSkillsSourceDir(projectRoot, skillId),\n 'SKILL.md',\n );\n const lines: string[] = [];\n lines.push(`### ${skillId}`);\n let parts: SkillDescriptionParts | null = null;\n let missing = false;\n try {\n const raw = await fs.readFile(skillPath, 'utf8');\n parts = extractDescriptionParts(raw);\n } catch {\n // SKILL.md missing — degrade gracefully, AI still gets the location hint.\n missing = true;\n }\n\n if (parts?.capability) {\n lines.push(`- ${parts.capability}`);\n }\n lines.push(\n `- **TRIGGER**: ${\n parts?.trigger ?? '未配置触发条件,需手动激活该 skill。'\n }`,\n );\n lines.push(\n `- **SKIP**: ${parts?.skip ?? '未配置跳过条件,按 TRIGGER 兜底判定。'}`,\n );\n if (parts?.coordinates) {\n lines.push(`- **Coordinates with**: ${parts.coordinates}`);\n }\n lines.push(`- **位置**: \\`.teamix-evo/skills-source/${skillId}/SKILL.md\\``);\n return { section: lines.join('\\n'), missing };\n}\n\nfunction renderAgentsMd(args: { variant: string; sections: string[] }): string {\n const { variant, sections } = args;\n const managedBody = renderManagedBlockBody({ variant, sections });\n const wrapped = wrapManagedBlock(managedBody);\n return `${wrapped}\\n\\n${PRECEDENCE_NOTICE}\\n`;\n}\n\n/**\n * Body of the `teamix-evo-skills` managed region (no enclosing markers).\n * Phase 2.B — isolated so {@link runGenerateAgentsMd} can substitute it via\n * `replaceManagedRegion` when reconciling against a user-edited AGENTS.md.\n *\n * Exported so external tools (e.g. the `teamix-evo-manage` skill) can render\n * a preview without depending on the file write path.\n */\nexport function renderManagedBlockBody(args: {\n variant: string;\n sections: string[];\n}): string {\n const { variant, sections } = args;\n const skillBlock =\n sections.length > 0\n ? sections.join('\\n\\n')\n : '_(本工程未装配工程级 skill。)_';\n return `# AGENTS.md\n\n> 本工程已装配 Teamix Evo AI skills。AI 助手在以下场景下**必须先读对应 skill** 再动手。\n> 本文件由 \\`teamix-evo init\\` / \\`create-teamix-evo\\` 自动生成(regenerable,遵循 ADR 0038),刷新方式见底部。\n\n## 已装 Skills(variant: ${variant})\n\n${skillBlock}\n\n## 触发兜底规则\n\n- 写新 \\`.tsx\\` / \\`.ts\\` 前,对照上述 TRIGGER 判定是否命中\n- 命中则先读对应 \\`SKILL.md\\`,再动手;二者同时命中则两个都读\n- 模糊场景:先按 SKIP 反向排除,剩余唯一 skill 即为入口\n- 生命周期命令(\\`init\\` / \\`update\\` / \\`add\\`)走 \\`teamix-evo-manage\\`(全局 skill,本文件不列)\n\n## UI 组件领地(init 后约束)\n\n- \\`src/components/ui/\\` 由 teamix-evo 接管,禁止手工或通过 shadcn CLI 添加新组件\n- 如需新增 UI 组件,使用 \\`npx teamix-evo ui add <id>\\`\n- \\`src/components/shadcn-ui/\\` 是 init 前 legacy 组件归档,只读;新代码不应再 import\n- 升级 legacy 组件:触发 teamix-evo-upgrade skill\n\n> 刷新本文件:\\`npx teamix-evo skills add\\` 或重跑 \\`npm create teamix-evo\\` / \\`teamix-evo init\\`。`;\n}\n\nfunction wrapManagedBlock(body: string): string {\n return `<!-- teamix-evo:managed:start id=\"${AGENTS_MD_MANAGED_ID}\" -->\\n${body}\\n<!-- teamix-evo:managed:end id=\"${AGENTS_MD_MANAGED_ID}\" -->`;\n}\n\n/**\n * Footer notice (Phase 2.B): when AGENTS.md hosts both managed and\n * user-authored sections, the managed Skills index wins on conflict.\n */\nconst PRECEDENCE_NOTICE = `<!-- teamix-evo:precedence -->\n> 冲突以上方的 **Skills** 索引为准(上游路径与 TRIGGER/SKIP 契约);项目特有的人工细则请写在本处以下、不要覆盖上方 managed 区域。`;\n\n// ─── frontmatter parsing ──────────────────────────────────────────────────────\n\n/**\n * Parse a SKILL.md frontmatter description into capability / TRIGGER / SKIP /\n * Coordinates parts.\n *\n * Why hand-rolled (no gray-matter): we only need the `description: |` block.\n * The full YAML grammar is overkill and adds a runtime dep to a CLI / scaffold\n * tool that should stay zero-cost. ADR 0015 keeps frontmatter shape stable.\n */\nexport function extractDescriptionParts(\n fileContent: string,\n): SkillDescriptionParts | null {\n const description = extractDescriptionBlock(fileContent);\n if (description == null) return null;\n\n // Capability = first line that is not a TRIGGER/SKIP/Coordinates marker.\n const allLines = description\n .split('\\n')\n .map((l) => l.trim())\n .filter(Boolean);\n let capability = '';\n for (const line of allLines) {\n if (/^(TRIGGER when:|SKIP:|Coordinates with:)/i.test(line)) break;\n capability = capability ? `${capability} ${line}` : line;\n }\n\n return {\n capability: capability.trim(),\n trigger: extractSection(description, 'TRIGGER when:'),\n skip: extractSection(description, 'SKIP:'),\n coordinates: extractSection(description, 'Coordinates with:'),\n };\n}\n\n/**\n * Extract the `description: |` (or `description: >`) block body. Returns null\n * if the field is missing or not a literal/folded block.\n */\nfunction extractDescriptionBlock(fileContent: string): string | null {\n const lines = fileContent.split('\\n');\n\n // Find frontmatter range: first `---`, then matching `---`.\n if (lines[0]?.trim() !== '---') return null;\n let endIdx = -1;\n for (let i = 1; i < lines.length; i++) {\n if (lines[i]?.trim() === '---') {\n endIdx = i;\n break;\n }\n }\n if (endIdx === -1) return null;\n const fmLines = lines.slice(1, endIdx);\n\n // Locate `description:` key.\n let startIdx = -1;\n let inlineValue: string | null = null;\n let blockMode: 'literal' | 'folded' | 'inline' = 'inline';\n for (let i = 0; i < fmLines.length; i++) {\n const m = fmLines[i]?.match(/^description:\\s*(\\|[+-]?|>[+-]?)?\\s*(.*)$/);\n if (m) {\n startIdx = i;\n const indicator = (m[1] ?? '').trim();\n const rest = m[2] ?? '';\n if (indicator.startsWith('|')) blockMode = 'literal';\n else if (indicator.startsWith('>')) blockMode = 'folded';\n else {\n blockMode = 'inline';\n inlineValue = rest;\n }\n break;\n }\n }\n if (startIdx === -1) return null;\n\n if (blockMode === 'inline') {\n return inlineValue ?? '';\n }\n\n // Block mode: collect indented continuation lines.\n const body: string[] = [];\n // Detect the block indent from the first non-empty continuation line.\n let blockIndent = -1;\n for (let i = startIdx + 1; i < fmLines.length; i++) {\n const line = fmLines[i] ?? '';\n if (line.trim() === '') {\n body.push('');\n continue;\n }\n const indentMatch = line.match(/^(\\s+)/);\n const indent = indentMatch ? indentMatch[1]!.length : 0;\n if (indent === 0) break; // back to top-level key\n if (blockIndent === -1) blockIndent = indent;\n if (indent < blockIndent) break;\n body.push(line.slice(blockIndent));\n }\n // Trim trailing empty lines.\n while (body.length > 0 && body[body.length - 1] === '') body.pop();\n return body.join('\\n');\n}\n\n/**\n * Extract the body of a description sub-section starting with the given\n * marker (e.g. \"TRIGGER when:\"). Stops at the next known marker or end of\n * description. Returns the stripped one-line summary (sub-section text with\n * internal newlines collapsed to spaces).\n */\nfunction extractSection(description: string, marker: string): string | null {\n const markers = ['TRIGGER when:', 'SKIP:', 'Coordinates with:'];\n const lines = description.split('\\n');\n let inSection = false;\n const collected: string[] = [];\n for (const line of lines) {\n const trimmed = line.trim();\n const startsWithMarker = trimmed\n .toLowerCase()\n .startsWith(marker.toLowerCase());\n if (!inSection && startsWithMarker) {\n inSection = true;\n collected.push(trimmed.slice(marker.length).trim());\n continue;\n }\n if (inSection) {\n const hitNextMarker = markers.some(\n (m) =>\n m !== marker && trimmed.toLowerCase().startsWith(m.toLowerCase()),\n );\n if (hitNextMarker) break;\n if (trimmed === '') {\n // Allow blank line within section but stop on second consecutive blank.\n if (collected[collected.length - 1] === '') break;\n collected.push('');\n continue;\n }\n collected.push(trimmed);\n }\n }\n if (!inSection) return null;\n const joined = collected\n .filter((l) => l !== '')\n .join(' ')\n .replace(/\\s+/g, ' ')\n .trim();\n return joined || null;\n}\n","import * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { fileExists } from '../utils/fs.js';\nimport { getTeamixDir } from './state.js';\n\n/**\n * Three branches of `teamix-evo init` decision tree (ADR 0019 D1).\n *\n * - `empty` : 空目录或仅含可忽略文件 → 推荐用户走 `npm create teamix-evo`(完整版)\n * - `teamix-evo-installed`: 已存在 `.teamix-evo/` → 推荐 `teamix-evo update` / 卸载流程\n * - `non-teamix-evo` : 已有非 teamix-evo 工程 → 走 `teamix-evo init` 普通版接入\n */\nexport type ProjectState = 'empty' | 'teamix-evo-installed' | 'non-teamix-evo';\n\nexport interface ProjectStateReport {\n /** Decision-tree branch the caller should take. */\n state: ProjectState;\n /** Absolute path that was inspected. */\n cwd: string;\n /** Whether `.teamix-evo/` exists at `cwd`. */\n hasTeamixDir: boolean;\n /** Whether `package.json` exists at `cwd`. */\n hasPackageJson: boolean;\n /**\n * Up to 20 entries (relative to `cwd`) that caused us to consider the\n * directory non-empty. Useful for explaining the decision to humans.\n */\n significantEntries: string[];\n}\n\n/**\n * Filenames that should NOT cause us to flip out of the `empty` branch.\n *\n * Mirrors the convention shared by `create-next-app`, `nx init`, and\n * `npm init` — these are typical files added by `git init`, an editor,\n * or the OS, not project content.\n */\nconst IGNORED_TOP_LEVEL = new Set<string>([\n '.git',\n '.gitignore',\n '.gitattributes',\n '.gitkeep',\n '.DS_Store',\n 'Thumbs.db',\n '.idea',\n '.vscode',\n '.qoder',\n '.claude',\n 'README.md',\n 'README',\n 'README.txt',\n 'LICENSE',\n 'LICENSE.md',\n 'LICENSE.txt',\n]);\n\n/**\n * Inspect `cwd` and decide which branch of the `teamix-evo init` decision\n * tree applies. Pure read-only — never mutates the filesystem.\n *\n * Resolution order (first match wins):\n * 1. `.teamix-evo/` exists → `teamix-evo-installed`\n * 2. cwd missing OR all entries are in the IGNORED_TOP_LEVEL set\n * → `empty`\n * 3. otherwise → `non-teamix-evo`\n */\nexport async function detectProjectState(\n cwd: string,\n): Promise<ProjectStateReport> {\n const absCwd = path.resolve(cwd);\n\n const teamixDir = getTeamixDir(absCwd);\n const hasTeamixDir = await fileExists(teamixDir);\n if (hasTeamixDir) {\n return {\n state: 'teamix-evo-installed',\n cwd: absCwd,\n hasTeamixDir: true,\n hasPackageJson: await fileExists(path.join(absCwd, 'package.json')),\n significantEntries: [],\n };\n }\n\n let entries: string[];\n try {\n entries = await fs.readdir(absCwd);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') {\n // Caller pointed us at a directory that doesn't exist yet — treat as\n // empty so `init` can create it (mirrors `npm create` behavior).\n return {\n state: 'empty',\n cwd: absCwd,\n hasTeamixDir: false,\n hasPackageJson: false,\n significantEntries: [],\n };\n }\n throw err;\n }\n\n const significant = entries.filter((e) => !IGNORED_TOP_LEVEL.has(e));\n const hasPackageJson = entries.includes('package.json');\n\n if (significant.length === 0) {\n return {\n state: 'empty',\n cwd: absCwd,\n hasTeamixDir: false,\n hasPackageJson: false,\n significantEntries: [],\n };\n }\n\n return {\n state: 'non-teamix-evo',\n cwd: absCwd,\n hasTeamixDir: false,\n hasPackageJson,\n significantEntries: significant.slice(0, 20).sort(),\n };\n}\n","import * as crypto from 'node:crypto';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { fileExists, readFileOrNull } from '../utils/fs.js';\n\n/**\n * The 8 categories of consumer-side files that `teamix-evo init` may\n * conflict with when running against a non-teamix-evo project.\n *\n * See ADR 0019 D1 task #5 — these are the only files we mutate at\n * `init` time, so they're the only ones we ask the user about.\n */\nexport type ConflictKey =\n | 'agents-md'\n | 'components-json'\n | 'tailwind-config'\n | 'tokens'\n | 'index-css'\n | 'shadcn-source'\n | 'eslint-config'\n | 'stylelint-config';\n\n/** Strategy options per conflict category. */\nexport type ConflictStrategy =\n // agents-md\n | 'overwrite'\n | 'merge-managed'\n | 'skip'\n // components-json\n | 'diff-prompt'\n // tailwind-config\n | 'backup-overwrite'\n // tokens\n | 'migrate'\n | 'coexist'\n // index-css\n | 'append'\n // shadcn-source\n | 'skip-existing'\n | 'per-file-prompt'\n // eslint-config / stylelint-config (Phase 3.E)\n | 'merge';\n\nexport interface ConflictItem {\n /** Stable id for the category. */\n key: ConflictKey;\n /** True if at least one path in `paths` matched on disk. */\n exists: boolean;\n /**\n * Project-relative paths that matched. Empty when `exists === false`.\n * For `shadcn-source`, may contain a directory path (with trailing `/`).\n */\n paths: string[];\n /** sha256 fingerprint of (sorted) matched contents. Omitted for directories or when nothing matched. */\n fingerprint?: string;\n /** Default strategy presented to the user. */\n recommendedStrategy: ConflictStrategy;\n /** All allowed strategies for this category, in display order. */\n availableStrategies: ConflictStrategy[];\n /** Category-specific metadata (e.g. detected tailwind major version). */\n meta?: Record<string, unknown>;\n}\n\nexport interface ConflictReport {\n cwd: string;\n /** Always 8 items, ordered by ConflictKey enumeration above. */\n items: ConflictItem[];\n /** True if any item has `exists === true`. */\n hasAnyConflict: boolean;\n}\n\n// ─── Path candidates per category ────────────────────────────────────────────\n\nconst TAILWIND_CONFIG_CANDIDATES = [\n 'tailwind.config.ts',\n 'tailwind.config.js',\n 'tailwind.config.cjs',\n 'tailwind.config.mjs',\n];\n\nconst TOKENS_FILE_CANDIDATES = [\n 'src/design-tokens.css',\n 'src/styles/design-tokens.css',\n 'src/styles/tokens.css',\n];\n\nconst TOKENS_DIR_CANDIDATES = ['tokens'];\n\nconst INDEX_CSS_CANDIDATES = [\n 'src/index.css',\n 'src/main.css',\n 'src/app.css',\n 'src/styles/index.css',\n 'src/styles/globals.css',\n];\n\nconst SHADCN_FILE_CANDIDATES = ['src/lib/utils.ts'];\nconst SHADCN_DIR_CANDIDATES = ['src/components/ui'];\n\n// Phase 3.E: 8 ESLint candidates (legacy `.eslintrc.*` + flat `eslint.config.*`)\nconst ESLINT_CONFIG_CANDIDATES = [\n '.eslintrc.cjs',\n '.eslintrc.js',\n '.eslintrc.json',\n '.eslintrc.yml',\n 'eslint.config.js',\n 'eslint.config.cjs',\n 'eslint.config.mjs',\n 'eslint.config.ts',\n];\n\n// Phase 3.E: 8 Stylelint candidates (legacy `.stylelintrc.*` + flat `stylelint.config.*`)\nconst STYLELINT_CONFIG_CANDIDATES = [\n '.stylelintrc.cjs',\n '.stylelintrc.js',\n '.stylelintrc.json',\n '.stylelintrc.yml',\n 'stylelint.config.cjs',\n 'stylelint.config.js',\n 'stylelint.config.mjs',\n 'stylelint.config.ts',\n];\n\n// ─── Helpers ─────────────────────────────────────────────────────────────────\n\nasync function isDir(target: string): Promise<boolean> {\n try {\n const stat = await fs.stat(target);\n return stat.isDirectory();\n } catch {\n return false;\n }\n}\n\nasync function dirHasContent(target: string): Promise<boolean> {\n try {\n const entries = await fs.readdir(target);\n return entries.length > 0;\n } catch {\n return false;\n }\n}\n\n/** Hash of UTF-8 string content; truncate to 16 chars for log readability. */\nfunction fingerprint(parts: string[]): string {\n const hash = crypto.createHash('sha256');\n for (const p of [...parts].sort()) hash.update(p);\n return `sha256:${hash.digest('hex').slice(0, 16)}`;\n}\n\ninterface PackageJsonShape {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n}\n\nasync function readPackageJson(cwd: string): Promise<PackageJsonShape | null> {\n const raw = await readFileOrNull(path.join(cwd, 'package.json'));\n if (raw === null) return null;\n try {\n return JSON.parse(raw) as PackageJsonShape;\n } catch {\n return null;\n }\n}\n\n/**\n * Detect tailwind major version from package.json.\n * Returns 4 / 3 / null. We trust dependencies + devDependencies.\n */\nfunction detectTailwindMajor(pkg: PackageJsonShape | null): 3 | 4 | null {\n if (!pkg) return null;\n const v =\n pkg.dependencies?.tailwindcss ?? pkg.devDependencies?.tailwindcss ?? null;\n if (!v) return null;\n // Accept \"^4.0.0\" / \"~4.2.2\" / \"4.x\" / \"next\" → conservative: parse leading digit\n const m = /(\\d+)/.exec(v);\n if (!m) return null;\n const major = Number.parseInt(m[1]!, 10);\n if (major === 3) return 3;\n if (major === 4) return 4;\n return null;\n}\n\n// ─── Per-category detectors ──────────────────────────────────────────────────\n\nasync function detectAgentsMd(cwd: string): Promise<ConflictItem> {\n const target = path.join(cwd, 'AGENTS.md');\n const content = await readFileOrNull(target);\n const exists = content !== null;\n return {\n key: 'agents-md',\n exists,\n paths: exists ? ['AGENTS.md'] : [],\n fingerprint: exists ? fingerprint([content!]) : undefined,\n recommendedStrategy: exists ? 'merge-managed' : 'overwrite',\n availableStrategies: ['merge-managed', 'overwrite', 'skip'],\n };\n}\n\nasync function detectComponentsJson(cwd: string): Promise<ConflictItem> {\n const target = path.join(cwd, 'components.json');\n const content = await readFileOrNull(target);\n const exists = content !== null;\n return {\n key: 'components-json',\n exists,\n paths: exists ? ['components.json'] : [],\n fingerprint: exists ? fingerprint([content!]) : undefined,\n recommendedStrategy: exists ? 'diff-prompt' : 'overwrite',\n availableStrategies: ['diff-prompt', 'overwrite', 'skip'],\n };\n}\n\nasync function detectTailwindConfig(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of TAILWIND_CONFIG_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const pkg = await readPackageJson(cwd);\n const tailwindMajor = detectTailwindMajor(pkg);\n const exists = matched.length > 0;\n return {\n key: 'tailwind-config',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'backup-overwrite' : 'overwrite',\n availableStrategies: ['backup-overwrite', 'overwrite', 'skip'],\n meta: { tailwindMajor },\n };\n}\n\nasync function detectTokens(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of TOKENS_FILE_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n for (const rel of TOKENS_DIR_CANDIDATES) {\n const abs = path.join(cwd, rel);\n if ((await isDir(abs)) && (await dirHasContent(abs))) {\n matched.push(`${rel}/`);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'tokens',\n exists,\n paths: matched,\n fingerprint: contents.length > 0 ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'migrate' : 'overwrite',\n availableStrategies: ['migrate', 'coexist', 'overwrite', 'skip'],\n };\n}\n\nasync function detectIndexCss(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of INDEX_CSS_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'index-css',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'append' : 'overwrite',\n availableStrategies: ['append', 'diff-prompt', 'overwrite', 'skip'],\n };\n}\n\nasync function detectShadcnSource(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n for (const rel of SHADCN_FILE_CANDIDATES) {\n if (await fileExists(path.join(cwd, rel))) matched.push(rel);\n }\n for (const rel of SHADCN_DIR_CANDIDATES) {\n const abs = path.join(cwd, rel);\n if ((await isDir(abs)) && (await dirHasContent(abs))) {\n matched.push(`${rel}/`);\n }\n }\n // For shadcn dir, count component files for meta.\n let componentCount = 0;\n try {\n const uiDir = path.join(cwd, 'src/components/ui');\n if (await isDir(uiDir)) {\n const entries = await fs.readdir(uiDir);\n componentCount = entries.filter(\n (e) => e.endsWith('.tsx') || e.endsWith('.ts'),\n ).length;\n }\n } catch {\n // ignore\n }\n const exists = matched.length > 0;\n return {\n key: 'shadcn-source',\n exists,\n paths: matched,\n recommendedStrategy: exists ? 'skip-existing' : 'overwrite',\n availableStrategies: ['skip-existing', 'per-file-prompt', 'overwrite'],\n meta: { componentCount },\n };\n}\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Inspect `cwd` for the 8 categories of files that `teamix-evo init` may\n * touch. Pure read-only — never mutates the filesystem. Returns one\n * `ConflictItem` per category in stable order so callers can render a\n * deterministic wizard.\n */\nexport async function detectConflicts(cwd: string): Promise<ConflictReport> {\n const absCwd = path.resolve(cwd);\n const items: ConflictItem[] = await Promise.all([\n detectAgentsMd(absCwd),\n detectComponentsJson(absCwd),\n detectTailwindConfig(absCwd),\n detectTokens(absCwd),\n detectIndexCss(absCwd),\n detectShadcnSource(absCwd),\n detectEslintConfig(absCwd),\n detectStylelintConfig(absCwd),\n ]);\n return {\n cwd: absCwd,\n items,\n hasAnyConflict: items.some((i) => i.exists),\n };\n}\n\nasync function detectEslintConfig(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of ESLINT_CONFIG_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'eslint-config',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'merge' : 'overwrite',\n availableStrategies: ['merge', 'backup-overwrite', 'overwrite', 'skip'],\n };\n}\n\nasync function detectStylelintConfig(cwd: string): Promise<ConflictItem> {\n const matched: string[] = [];\n const contents: string[] = [];\n for (const rel of STYLELINT_CONFIG_CANDIDATES) {\n const c = await readFileOrNull(path.join(cwd, rel));\n if (c !== null) {\n matched.push(rel);\n contents.push(c);\n }\n }\n const exists = matched.length > 0;\n return {\n key: 'stylelint-config',\n exists,\n paths: matched,\n fingerprint: exists ? fingerprint(contents) : undefined,\n recommendedStrategy: exists ? 'merge' : 'overwrite',\n availableStrategies: ['merge', 'backup-overwrite', 'overwrite', 'skip'],\n };\n}\n","/**\n * npm dependency auto-installer for `teamix-evo init`.\n *\n * After `runUiAdd` completes, this module:\n * 1. Collects `npmDependencies` from the install result\n * 2. Reads the project's `package.json`\n * 3. Writes missing deps into `dependencies`\n * 4. Detects the package manager and runs install\n *\n * See PLAN Task 3.8 (P0).\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { fileExists, readFileOrNull } from '../utils/fs.js';\nimport { logger } from '../utils/logger.js';\n\nconst execAsync = promisify(exec);\n\n// ─── Public types ────────────────────────────────────────────────────────────\n\nexport interface DepsInstallOptions {\n /** Absolute project root */\n projectRoot: string;\n /** npm dependencies to install (name → semver range) */\n npmDependencies: Record<string, string>;\n /** Skip the actual install command (just patch package.json) */\n skipInstall?: boolean;\n}\n\nexport interface DepsInstallResult {\n /** Deps newly written to package.json */\n added: Record<string, string>;\n /** Deps that already existed (skipped) */\n existed: Record<string, string>;\n /** Whether install command was executed */\n installed: boolean;\n /** Detected package manager */\n packageManager: PackageManager;\n}\n\n// ─── Package manager detection ───────────────────────────────────────────────\n\ntype PackageManager = 'pnpm' | 'yarn' | 'bun' | 'npm';\n\nasync function detectPackageManager(\n projectRoot: string,\n): Promise<PackageManager> {\n if (await fileExists(path.join(projectRoot, 'pnpm-lock.yaml'))) return 'pnpm';\n if (await fileExists(path.join(projectRoot, 'pnpm-workspace.yaml')))\n return 'pnpm';\n if (await fileExists(path.join(projectRoot, 'bun.lockb'))) return 'bun';\n if (await fileExists(path.join(projectRoot, 'bun.lock'))) return 'bun';\n if (await fileExists(path.join(projectRoot, 'yarn.lock'))) return 'yarn';\n return 'npm';\n}\n\nfunction getInstallCommand(pm: PackageManager): string {\n switch (pm) {\n case 'pnpm':\n return 'pnpm install';\n case 'yarn':\n return 'yarn install';\n case 'bun':\n return 'bun install';\n case 'npm':\n return 'npm install';\n }\n}\n\n// ─── Core installer ──────────────────────────────────────────────────────────\n\n/**\n * Patch project `package.json` with missing npm dependencies and optionally\n * run the package manager's install command.\n */\nexport async function installProjectDeps(\n options: DepsInstallOptions,\n): Promise<DepsInstallResult> {\n const { projectRoot, npmDependencies, skipInstall = false } = options;\n\n const pkgPath = path.join(projectRoot, 'package.json');\n const raw = await readFileOrNull(pkgPath);\n if (!raw) {\n throw new Error(\n `package.json not found at ${projectRoot}. Cannot install dependencies.`,\n );\n }\n\n const pkg = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n const existingDeps = {\n ...pkg.dependencies,\n ...pkg.devDependencies,\n };\n\n const added: Record<string, string> = {};\n const existed: Record<string, string> = {};\n\n for (const [name, range] of Object.entries(npmDependencies)) {\n if (existingDeps[name]) {\n existed[name] = existingDeps[name]!;\n } else {\n added[name] = range;\n }\n }\n\n // Patch package.json if there are new deps\n if (Object.keys(added).length > 0) {\n if (!pkg.dependencies) pkg.dependencies = {};\n for (const [name, range] of Object.entries(added)) {\n pkg.dependencies[name] = range;\n }\n // Sort dependencies alphabetically\n pkg.dependencies = Object.fromEntries(\n Object.entries(pkg.dependencies).sort(([a], [b]) => a.localeCompare(b)),\n );\n\n await fs.writeFile(pkgPath, JSON.stringify(pkg, null, 2) + '\\n', 'utf-8');\n logger.info(\n ` patched package.json: +${Object.keys(added).length} dependencies`,\n );\n }\n\n // Detect package manager and run install\n const packageManager = await detectPackageManager(projectRoot);\n let installed = false;\n\n if (!skipInstall && Object.keys(added).length > 0) {\n const cmd = getInstallCommand(packageManager);\n logger.info(` running ${cmd}...`);\n try {\n await execAsync(cmd, { cwd: projectRoot, timeout: 120_000 });\n installed = true;\n logger.info(' install complete');\n } catch (err) {\n logger.warn(\n ` install failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n logger.warn(' please run install manually');\n }\n }\n\n return { added, existed, installed, packageManager };\n}\n","/**\n * Generates the `.teamix-evo/init-checklist.md` content after `teamix-evo init`.\n *\n * Simplified for ADR 0043: only records the 8-step pipeline results.\n * No Phase B — post-init guidance is handled by AI skills at runtime.\n */\n\nimport type { ProjectInitStep } from './project-init.js';\n\n/** Step display metadata. */\nconst STEP_LABELS: Record<string, string> = {\n tokens: 'tokens — design tokens 安装',\n skills: 'skills — AI skills 批量自举',\n 'agents-md': 'agents-md — AGENTS.md 生成',\n 'ui-init': 'ui-init — UI 配置初始化',\n 'ui-add': 'ui-add — UI 组件全量安装',\n 'biz-ui-add': 'biz-ui-add — 业务组件全量安装',\n lint: 'lint — ESLint + Stylelint 配置',\n gitignore: 'gitignore — .gitignore 追加',\n};\n\nexport function renderInitChecklist(args: {\n variant: string;\n status: string;\n steps: ProjectInitStep[];\n timestamp?: string;\n}): string {\n const { variant, status, steps } = args;\n const ts =\n args.timestamp ?? new Date().toISOString().replace('T', ' ').slice(0, 19);\n\n const stepLines = steps\n .map((s) => {\n const label = STEP_LABELS[s.name] ?? s.name;\n const checked = s.status === 'ok' ? 'x' : ' ';\n const suffix =\n s.status === 'ok'\n ? ''\n : s.status === 'skip'\n ? `(跳过${s.detail ? ':' + s.detail : ''})`\n : s.status === 'fail'\n ? `(失败:${s.detail ?? 'unknown'})`\n : '(计划中)';\n return `- [${checked}] ${label}${suffix}`;\n })\n .join('\\n');\n\n return `# teamix-evo init 安装摘要\n\n> 由 \\`teamix-evo init\\` 自动生成 · ${ts}\n> variant: ${variant} · status: ${status}\n\n## 安装步骤\n\n${stepLines}\n\n## 备注\n\n- 失败或跳过的步骤不影响后续步骤独立执行\n- 修复后重跑 \\`teamix-evo init\\`(每步幂等,自动跳过已完成项)\n- 如需全量覆盖:\\`teamix-evo init --force\\`\n`;\n}\n","/**\n * File-change ledger for the init / update pipelines.\n *\n * Phase 1.A1 (init 落地改进): every orchestrator step records what it touched\n * so the CLI can print a single \"新建 / 修改 / 备份 / 删除\" summary at the end.\n * Today's pipeline only piggybacks on side-effectful sub-commands' result\n * objects (`resources`, `wroteEslint`, …) — without an explicit ledger the\n * user has no way to see, in one glance, which user-owned files moved.\n *\n * Design constraints:\n * - Pure data type — no I/O, no global mutable state. The orchestrator passes\n * a single mutable array down to each helper; sub-step adapters return\n * `FileChange[]` they can derive from their own return values.\n * - \"modified\" vs \"created\" is decided by checking whether a fresh backup\n * exists under `.teamix-evo/.backups/<rel>.*.bak` for that path — see\n * {@link diffBackupSet}. Any path that gained a backup during the pipeline\n * is classified `modified`; everything else surfaced by the steps is\n * `created`. This keeps the classification truthful even when a sub-step\n * has no idea whether the file pre-existed.\n */\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\nexport type FileChangeKind = 'created' | 'modified' | 'backed-up' | 'deleted';\n\nexport interface FileChange {\n kind: FileChangeKind;\n /** Project-root-relative path, posix style (forward slashes). */\n path: string;\n /** Originating pipeline step (free-form to avoid coupling on `ProjectInitStepName`). */\n step: string;\n /** Optional human-readable note (e.g. `frozen` / `regenerable` / `managed`). */\n detail?: string;\n}\n\n/**\n * Convert any abs/rel path to a project-root-relative posix path.\n * Returns the input unchanged if it cannot be relativised.\n */\nexport function toRelativePosix(p: string, projectRoot: string): string {\n let rel = p;\n if (path.isAbsolute(p)) {\n rel = path.relative(projectRoot, p);\n }\n return rel.split(path.sep).join('/');\n}\n\n/**\n * Recursively enumerate `.teamix-evo/.backups/` and return the set of\n * original (project-root-relative) paths that have at least one `.bak` copy.\n *\n * Backup file names follow `<rel>.<isoTsSafe>.bak` where `<isoTsSafe>` is the\n * output of `new Date().toISOString().replace(/[:.]/g, '-')` — a fixed-shape\n * `YYYY-MM-DDTHH-MM-SS-mmmZ` token. We strip that suffix to recover `<rel>`.\n *\n * Returns an empty set when the backups directory does not exist.\n */\nexport async function listBackupOriginals(\n projectRoot: string,\n): Promise<Set<string>> {\n const backupsDir = path.join(projectRoot, '.teamix-evo', '.backups');\n const out = new Set<string>();\n const stack: string[] = [backupsDir];\n while (stack.length > 0) {\n const dir = stack.pop()!;\n let entries: import('node:fs').Dirent[];\n try {\n entries = await fs.readdir(dir, { withFileTypes: true });\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'ENOENT') continue;\n throw err;\n }\n for (const e of entries) {\n const full = path.join(dir, e.name);\n if (e.isDirectory()) {\n stack.push(full);\n } else if (e.isFile() && e.name.endsWith('.bak')) {\n const rel = path.relative(backupsDir, full);\n const original = stripBackupSuffix(rel);\n if (original) out.add(original.split(path.sep).join('/'));\n }\n }\n }\n return out;\n}\n\n/**\n * Strip the `.<isoTsSafe>.bak` tail from a backup-relative path. Returns null\n * when the suffix doesn't match (file isn't one of ours — leave untouched).\n */\nexport function stripBackupSuffix(rel: string): string | null {\n const m = rel.match(\n /^(.+)\\.\\d{4}-\\d{2}-\\d{2}T\\d{2}-\\d{2}-\\d{2}-\\d{3}Z\\.bak$/,\n );\n return m?.[1] ?? null;\n}\n\n/**\n * Compute the relative-path set that gained a fresh backup between `before`\n * and `after` (i.e. paths the pipeline modified in-place).\n */\nexport function diffBackupSet(\n before: ReadonlySet<string>,\n after: ReadonlySet<string>,\n): Set<string> {\n const out = new Set<string>();\n for (const p of after) {\n if (!before.has(p)) out.add(p);\n }\n return out;\n}\n\n/**\n * Format a flat list of `FileChange` rows into a markdown-ish summary.\n * Returns an array of lines suitable for the CLI logger.\n *\n * Empty buckets are omitted from the output. Order: created → modified →\n * backed-up → deleted. Each bucket lists paths sorted lexicographically with\n * de-duplication on `(kind, path)`.\n */\nexport function formatFileChangeSummary(changes: FileChange[]): string[] {\n if (changes.length === 0) return [];\n const buckets: Record<FileChangeKind, Map<string, FileChange>> = {\n created: new Map(),\n modified: new Map(),\n 'backed-up': new Map(),\n deleted: new Map(),\n };\n for (const c of changes) {\n const existing = buckets[c.kind].get(c.path);\n if (!existing) buckets[c.kind].set(c.path, c);\n }\n const order: Array<[FileChangeKind, string]> = [\n ['created', '🆕 新建'],\n ['modified', '✏️ 修改'],\n ['backed-up', '💾 已备份'],\n ['deleted', '🗑 删除'],\n ];\n const lines: string[] = [];\n for (const [kind, label] of order) {\n const bucket = buckets[kind];\n if (bucket.size === 0) continue;\n lines.push(`${label}(${bucket.size}):`);\n const sorted = [...bucket.values()].sort((a, b) =>\n a.path.localeCompare(b.path),\n );\n for (const c of sorted) {\n const detail = c.detail ? ` — ${c.detail}` : '';\n lines.push(` • ${c.path} [${c.step}]${detail}`);\n }\n }\n return lines;\n}\n","/**\n * Programmatic orchestrator for `teamix-evo init` (ADR 0043).\n *\n * Drives the 8-step pipeline that installs the full teamix-evo suite into an\n * existing project. Each step is idempotent — re-running `init` picks up from\n * where it left off.\n *\n * Conflict handling is intentionally thin (ADR 0043 §3): detect → terminate →\n * structured output → AI decides. The orchestrator only checks `force` — when\n * true, it skips conflict detection entirely.\n */\nimport type { SkillIde, SkillScope } from '@teamix-evo/registry';\nimport { runTokensInit } from './tokens-init.js';\nimport { runSkillsInit } from './skills-add.js';\nimport { runGenerateAgentsMd } from './agents-md.js';\nimport { runUiInit } from './ui-init.js';\nimport { runUiAdd } from './ui-add.js';\nimport { runBizUiAdd, listBizUiEntries } from './variant-ui-add.js';\nimport { runLintInit } from './lint-init.js';\nimport { installProjectDeps } from './deps-install.js';\nimport { loadUiData } from './ui-client.js';\nimport { renderInitChecklist } from './init-checklist-template.js';\nimport { getErrorMessage } from '../utils/error.js';\nimport { logger } from '../utils/logger.js';\nimport { type FileChange, toRelativePosix } from './file-changes.js';\nimport * as fsNode from 'node:fs/promises';\nimport * as path from 'node:path';\n\n// ─── Types ─────────────────────────────────────────────────────────────────────\n\nexport type ProjectInitStepName =\n | 'tokens'\n | 'skills'\n | 'agents-md'\n | 'ui-init'\n | 'ui-add'\n | 'biz-ui-add'\n | 'lint'\n | 'gitignore';\n\nexport type ProjectInitStepStatus = 'ok' | 'skip' | 'fail' | 'planned';\n\nexport interface ProjectInitStep {\n name: ProjectInitStepName;\n status: ProjectInitStepStatus;\n detail?: string;\n /** Files this step touched. */\n changes?: FileChange[];\n}\n\nexport interface ResumeHint {\n failedAt: ProjectInitStepName;\n completed: ProjectInitStepName[];\n failed: ProjectInitStepName[];\n error: string;\n resumeCommand: string;\n}\n\nexport interface RunProjectInitOptions {\n /** Absolute project root (existing repo to adopt teamix-evo into). */\n projectRoot: string;\n /** Tokens variant (e.g. \"opentrek\" / \"uni-manager\"). */\n variant: string;\n /** Target IDEs (at least one). */\n ides: SkillIde[];\n /** Skill install scope. Defaults to 'project'. */\n scope?: SkillScope;\n /**\n * When true, skip conflict detection and overwrite everything.\n * Distinction: init --force = skip conflict check; create --force = overwrite directory.\n */\n force?: boolean;\n /** Skip `npm install` for lint deps. */\n skipInstall?: boolean;\n /** Step-level progress hook. */\n onStep?: (step: ProjectInitStep) => void;\n /** Plan-only mode: compute steps without running sub-commands. */\n dryRun?: boolean;\n}\n\nexport interface RunProjectInitResult {\n status: 'installed' | 'partial' | 'dry-run';\n steps: ProjectInitStep[];\n changes: FileChange[];\n resumeHint?: ResumeHint;\n}\n\n// ─── Constants ──────────────────────────────────────────────────────────────────\n\n/**\n * Steps whose failure aborts subsequent critical steps. Non-critical leaves\n * (agents-md / ui-add / biz-ui-add / lint / gitignore) continue independently.\n */\nconst CRITICAL_STEPS: ReadonlySet<ProjectInitStepName> = new Set([\n 'tokens',\n 'skills',\n 'ui-init',\n]);\n\nconst GITIGNORE_MARKER_START = '# >>> teamix-evo:managed >>>';\nconst GITIGNORE_MARKER_END = '# <<< teamix-evo:managed <<<';\nconst GITIGNORE_RULES = [\n '# IDE skill mirrors (regenerable via `teamix-evo skills sync`; ADR 0013)',\n '.qoder/skills/',\n '.claude/skills/',\n '',\n '# Runtime artifacts (regenerable / archives)',\n '.teamix-evo/.snapshots/',\n '.teamix-evo/logs/',\n '.teamix-evo/.backups/',\n '.teamix-evo/.upgrade-staging/',\n '.teamix-evo/.upgrade-hints/',\n];\n\n// ─── Orchestrator ───────────────────────────────────────────────────────────────\n\nexport async function runProjectInit(\n options: RunProjectInitOptions,\n): Promise<RunProjectInitResult> {\n const {\n projectRoot,\n variant,\n ides,\n scope = 'project',\n dryRun = false,\n onStep,\n } = options;\n const ide = ides[0] ?? 'qoder';\n const steps: ProjectInitStep[] = [];\n const allChanges: FileChange[] = [];\n\n let aborted = false;\n const firstFailure: {\n value: { step: ProjectInitStepName; error: string } | null;\n } = { value: null };\n\n function record(step: ProjectInitStep): void {\n steps.push(step);\n onStep?.(step);\n if (step.changes && step.changes.length > 0) {\n allChanges.push(...step.changes);\n }\n }\n\n function recordFailure(name: ProjectInitStepName, err: unknown): void {\n const message = getErrorMessage(err);\n record({ name, status: 'fail', detail: message });\n if (!firstFailure.value)\n firstFailure.value = { step: name, error: message };\n if (CRITICAL_STEPS.has(name)) aborted = true;\n }\n\n // ─── 1. tokens ──────────────────────────────────────────────────────────────\n if (dryRun) {\n record({\n name: 'tokens',\n status: 'planned',\n detail: `runTokensInit(variant=${variant})`,\n });\n } else {\n try {\n const result = await runTokensInit({ projectRoot, variant, ide });\n const detail =\n result.status === 'installed'\n ? `${result.packageName}@${result.version} (${result.count} files)`\n : result.status;\n record({\n name: 'tokens',\n status: 'ok',\n detail,\n changes:\n result.status === 'installed'\n ? result.resources.map((r) => ({\n kind: 'created' as const,\n path: toRelativePosix(r.target, projectRoot),\n step: 'tokens',\n detail: r.strategy,\n }))\n : [],\n });\n } catch (err) {\n recordFailure('tokens', err);\n }\n }\n\n // ─── 2. skills init (batch bootstrap) ────────────────────────────────────────\n if (dryRun) {\n record({\n name: 'skills',\n status: 'planned',\n detail: `runSkillsInit(scope=${scope})`,\n });\n } else if (aborted) {\n record({\n name: 'skills',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n } else {\n try {\n const result = await runSkillsInit({ projectRoot, ides, scope, ide });\n if (result.status === 'already-initialized') {\n record({ name: 'skills', status: 'ok', detail: 'already-initialized' });\n } else {\n record({\n name: 'skills',\n status: 'ok',\n detail: `${result.skillCount} skills, ${\n result.fileCount\n } files (added: ${result.addedSkillIds.join(', ') || 'none'})`,\n changes: result.addedSkillIds.map((id) => ({\n kind: 'created' as const,\n path: `.teamix-evo/skills/${id}/SKILL.md`,\n step: 'skills',\n detail: 'skill installed',\n })),\n });\n }\n } catch (err) {\n recordFailure('skills', err);\n }\n }\n\n // ─── 3. AGENTS.md ─────────────────────────────────────────────────────────────\n if (dryRun) {\n record({\n name: 'agents-md',\n status: 'planned',\n detail: 'runGenerateAgentsMd()',\n });\n } else {\n try {\n const result = await runGenerateAgentsMd({\n projectRoot,\n variant,\n skillIds: [\n `teamix-evo-design-${variant}`,\n `teamix-evo-code-${variant}`,\n ],\n mode: 'merge-managed',\n });\n record({\n name: 'agents-md',\n status: 'ok',\n detail: `${result.skillCount} skill index`,\n changes: [\n {\n kind: result.backedUp ? 'modified' : 'created',\n path: toRelativePosix(result.path, projectRoot),\n step: 'agents-md',\n detail: 'skill-trigger fallback (ADR 0038)',\n },\n ],\n });\n } catch (err) {\n recordFailure('agents-md', err);\n }\n }\n\n // ─── 4. ui-init (.teamix-evo/config.json) ──────────────────────────────────────\n if (dryRun) {\n record({ name: 'ui-init', status: 'planned', detail: 'runUiInit()' });\n } else if (aborted) {\n record({\n name: 'ui-init',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n } else {\n try {\n const initResult = await runUiInit({ projectRoot, ide });\n record({\n name: 'ui-init',\n status: 'ok',\n detail:\n initResult.status === 'installed'\n ? 'config.json packages.ui written'\n : initResult.status,\n });\n } catch (err) {\n recordFailure('ui-init', err);\n }\n }\n\n // ─── 5. ui add --all (全量 UI 组件源码) ────────────────────────────────────────\n // 收集 ui-add + biz-ui-add 的 npm 依赖,统一在两步之后调用 installProjectDeps。\n const collectedNpmDeps: Record<string, string> = {};\n if (dryRun) {\n const { manifest } = await loadUiData('@teamix-evo/ui').catch(() => ({\n manifest: { entries: [] as Array<{ id: string }> },\n }));\n record({\n name: 'ui-add',\n status: 'planned',\n detail: `runUiAdd(${manifest.entries.length} entries, --all)`,\n });\n } else if (aborted) {\n record({\n name: 'ui-add',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n } else {\n try {\n const { manifest } = await loadUiData('@teamix-evo/ui');\n const allIds = manifest.entries.map((e) => e.id);\n const addResult = await runUiAdd({\n projectRoot,\n ids: allIds,\n overwrite: true,\n });\n // slice(-0) === slice(0) 返回全量;written === 0 时显式返回空数组\n const writtenResources =\n addResult.written > 0\n ? addResult.resources.slice(-addResult.written)\n : [];\n record({\n name: 'ui-add',\n status: 'ok',\n detail: `${addResult.orderedIds.length} entries (${addResult.written} written, ${addResult.skipped} skipped)`,\n changes: writtenResources.map((r) => ({\n kind: 'created' as const,\n path: toRelativePosix(r.target, projectRoot),\n step: 'ui-add',\n detail: r.strategy,\n })),\n });\n Object.assign(collectedNpmDeps, addResult.npmDependencies);\n } catch (err) {\n recordFailure('ui-add', err);\n }\n }\n\n // ─── 6. biz-ui add --all (variant 全量业务组件) ─────────────────────────────────\n if (dryRun) {\n try {\n const listing = await listBizUiEntries(variant);\n record({\n name: 'biz-ui-add',\n status: 'planned',\n detail: `runBizUiAdd(variant=${variant}, ${listing.entries.length} entries)`,\n });\n } catch {\n record({\n name: 'biz-ui-add',\n status: 'planned',\n detail: `runBizUiAdd(variant=${variant})`,\n });\n }\n } else if (aborted) {\n record({\n name: 'biz-ui-add',\n status: 'skip',\n detail: 'aborted: earlier critical step failed',\n });\n } else {\n try {\n const listing = await listBizUiEntries(variant);\n if (listing.entries.length === 0) {\n record({\n name: 'biz-ui-add',\n status: 'skip',\n detail: `no biz-ui entries for variant \"${variant}\"`,\n });\n } else {\n const allIds = listing.entries.map((e) => e.id);\n const result = await runBizUiAdd({\n projectRoot,\n variant,\n ids: allIds,\n overwrite: true,\n });\n record({\n name: 'biz-ui-add',\n status: 'ok',\n detail: `${result.orderedIds.length} entries (${result.written} written, ${result.skipped} skipped)`,\n });\n if (result.npmDependencies) {\n Object.assign(collectedNpmDeps, result.npmDependencies);\n }\n }\n } catch (err) {\n recordFailure('biz-ui-add', err);\n }\n }\n\n // ─── 6.5 install ui / biz-ui transitive npm dependencies ─────────────────────\n // ui-add / biz-ui-add 复制源码后,需要把它们引用的 npm 依赖(@radix-ui/* / cmdk /\n // recharts 等)写入 package.json 并安装,否则 `npm run dev` 会报模块缺失。\n if (!dryRun && !aborted && Object.keys(collectedNpmDeps).length > 0) {\n try {\n await installProjectDeps({\n projectRoot,\n npmDependencies: collectedNpmDeps,\n skipInstall: options.skipInstall ?? false,\n });\n } catch (err) {\n // Non-critical: 失败不应阻断 lint / gitignore;记录但不计入 critical abort。\n logger.warn(\n `安装 ui/biz-ui 传递依赖失败:${getErrorMessage(\n err,\n )}(可手动运行 \\`npm install\\` 重试)`,\n );\n }\n }\n\n // ─── 7. lint init ──────────────────────────────────────────────────────────────\n if (dryRun) {\n record({ name: 'lint', status: 'planned', detail: 'runLintInit()' });\n } else {\n try {\n const result = await runLintInit({\n projectRoot,\n skipInstall: options.skipInstall ?? false,\n eslintStrategy: 'overwrite',\n stylelintStrategy: 'overwrite',\n eslintExistingPaths: [],\n stylelintExistingPaths: [],\n });\n const detailParts: string[] = [];\n if (result.status === 'installed') {\n detailParts.push(\n `eslint=${result.eslint}, stylelint=${result.stylelint}`,\n );\n if (result.packageJsonPatched) detailParts.push('package.json patched');\n } else {\n detailParts.push(result.status);\n }\n record({\n name: 'lint',\n status: 'ok',\n detail: detailParts.join(' / '),\n changes: deriveLintChanges(result),\n });\n } catch (err) {\n recordFailure('lint', err);\n }\n }\n\n // ─── 8. gitignore ──────────────────────────────────────────────────────────────\n if (dryRun) {\n record({\n name: 'gitignore',\n status: 'planned',\n detail: 'append teamix-evo runtime rules',\n });\n } else {\n try {\n let projectRootExists = true;\n try {\n await fsNode.access(projectRoot);\n } catch {\n projectRootExists = false;\n }\n if (!projectRootExists) {\n record({\n name: 'gitignore',\n status: 'skip',\n detail: 'projectRoot does not exist',\n });\n } else {\n const giPath = path.join(projectRoot, '.gitignore');\n let giContent = '';\n try {\n giContent = await fsNode.readFile(giPath, 'utf-8');\n } catch {\n // .gitignore doesn't exist yet — we'll create it\n }\n if (giContent.includes(GITIGNORE_MARKER_START)) {\n record({\n name: 'gitignore',\n status: 'skip',\n detail: 'teamix-evo markers already present',\n });\n } else {\n const block = [\n '',\n GITIGNORE_MARKER_START,\n ...GITIGNORE_RULES,\n GITIGNORE_MARKER_END,\n '',\n ].join('\\n');\n const separator =\n giContent.length > 0 && !giContent.endsWith('\\n') ? '\\n' : '';\n await fsNode.writeFile(\n giPath,\n giContent + separator + block,\n 'utf-8',\n );\n record({\n name: 'gitignore',\n status: 'ok',\n detail: `${GITIGNORE_RULES.filter((r) => r && !r.startsWith('#')).length} rules appended`,\n changes: [\n {\n kind: 'modified',\n path: '.gitignore',\n step: 'gitignore',\n detail: 'teamix-evo runtime artifact rules',\n },\n ],\n });\n }\n }\n } catch (err) {\n recordFailure('gitignore', err);\n }\n }\n\n // ─── Result assembly ──────────────────────────────────────────────────────────\n const status: RunProjectInitResult['status'] = dryRun\n ? 'dry-run'\n : steps.some((s) => s.status === 'fail')\n ? 'partial'\n : 'installed';\n\n const out: RunProjectInitResult = { status, steps, changes: allChanges };\n\n if (firstFailure.value) {\n out.resumeHint = {\n failedAt: firstFailure.value.step,\n completed: steps.filter((s) => s.status === 'ok').map((s) => s.name),\n failed: steps.filter((s) => s.status === 'fail').map((s) => s.name),\n error: firstFailure.value.error,\n resumeCommand: 'teamix-evo init',\n };\n }\n\n // Write install summary (.teamix-evo/init-checklist.md)\n if (!dryRun) {\n try {\n const checklistContent = renderInitChecklist({ variant, status, steps });\n const checklistPath = path.join(\n projectRoot,\n '.teamix-evo',\n 'init-checklist.md',\n );\n await fsNode.mkdir(path.dirname(checklistPath), { recursive: true });\n await fsNode.writeFile(checklistPath, checklistContent, 'utf-8');\n logger.info(' wrote .teamix-evo/init-checklist.md');\n } catch {\n logger.warn(' failed to write init-checklist.md (non-fatal)');\n }\n }\n\n return out;\n}\n\n// ─── Helpers ────────────────────────────────────────────────────────────────────\n\ntype LintInitResult = Awaited<ReturnType<typeof runLintInit>>;\n\nfunction deriveLintChanges(result: LintInitResult): FileChange[] {\n if (result.status !== 'installed') return [];\n const out: FileChange[] = [];\n if (result.eslint) {\n out.push({\n kind: 'created',\n path: 'eslint.config.js',\n step: 'lint',\n detail: '@teamix-evo/eslint-config',\n });\n }\n if (result.stylelint) {\n out.push({\n kind: 'created',\n path: 'stylelint.config.cjs',\n step: 'lint',\n detail: '@teamix-evo/stylelint-config',\n });\n }\n if (result.packageJsonPatched) {\n out.push({\n kind: 'created',\n path: 'package.json',\n step: 'lint',\n detail: 'scripts.lint / scripts[\"lint:css\"]',\n });\n }\n return out;\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport type {\n VariantManifest,\n Resource,\n InstalledResource,\n} from '@teamix-evo/registry';\nimport { writeFileSafe, ensureDir } from '../utils/fs.js';\nimport { computeHash } from '../utils/hash.js';\nimport { renderTemplate, loadTemplateFile } from '../utils/template.js';\nimport { logger } from '../utils/logger.js';\nimport { resolveSourcePath, walkDir } from '../utils/path.js';\n\nexport interface InstallOptions {\n /** Project root directory */\n projectRoot: string;\n /** The variant manifest */\n manifest: VariantManifest;\n /** Template data for Handlebars rendering */\n data: Record<string, unknown>;\n /** Absolute path to the variant directory (where source files live) */\n variantDir: string;\n /** Absolute path to the package root (for resolving _template/ sources) */\n packageRoot: string;\n}\n\nexport interface InstallResult {\n /** Successfully installed resource records */\n resources: InstalledResource[];\n /** Number of resources installed */\n count: number;\n}\n\n/**\n * Install resources from a variant manifest into the project.\n */\nexport async function installResources(\n options: InstallOptions,\n): Promise<InstallResult> {\n const { projectRoot, manifest, data, variantDir, packageRoot } = options;\n const installedResources: InstalledResource[] = [];\n\n for (const resource of manifest.resources) {\n logger.debug(`Installing resource: ${resource.id} → ${resource.target}`);\n\n if (resource.recursive) {\n const results = await installRecursiveResource(\n resource,\n projectRoot,\n data,\n variantDir,\n packageRoot,\n );\n installedResources.push(...results);\n } else {\n const result = await installSingleResource(\n resource,\n projectRoot,\n data,\n variantDir,\n packageRoot,\n );\n installedResources.push(result);\n }\n }\n\n return {\n resources: installedResources,\n count: installedResources.length,\n };\n}\n\n/**\n * Install a single (non-recursive) resource.\n */\nasync function installSingleResource(\n resource: Resource,\n projectRoot: string,\n data: Record<string, unknown>,\n variantDir: string,\n packageRoot: string,\n): Promise<InstalledResource> {\n const sourcePath = resolveSourcePath(\n resource.source,\n variantDir,\n packageRoot,\n );\n const targetPath = path.join(projectRoot, resource.target);\n\n let content: string;\n if (resource.template) {\n const templateContent = await loadTemplateFile(sourcePath);\n content = renderTemplate(templateContent, data);\n } else {\n content = await fs.readFile(sourcePath, 'utf-8');\n }\n\n await writeFileSafe(targetPath, content);\n const hash = computeHash(content);\n\n logger.debug(` Written: ${resource.target} (${resource.updateStrategy})`);\n\n return {\n id: resource.id,\n target: resource.target,\n hash,\n strategy: resource.updateStrategy,\n };\n}\n\n/**\n * Install a recursive resource (directory).\n */\nasync function installRecursiveResource(\n resource: Resource,\n projectRoot: string,\n data: Record<string, unknown>,\n variantDir: string,\n packageRoot: string,\n): Promise<InstalledResource[]> {\n const sourcePath = resolveSourcePath(\n resource.source,\n variantDir,\n packageRoot,\n );\n const targetDir = path.join(projectRoot, resource.target);\n const results: InstalledResource[] = [];\n\n await ensureDir(targetDir);\n\n const entries = await walkDir(sourcePath);\n for (const entry of entries) {\n const relPath = path.relative(sourcePath, entry);\n let targetFile = path.join(targetDir, relPath);\n\n // Strip .hbs extension from target if template\n if (resource.template && targetFile.endsWith('.hbs')) {\n targetFile = targetFile.slice(0, -4);\n }\n\n let content: string;\n if (resource.template && entry.endsWith('.hbs')) {\n const templateContent = await loadTemplateFile(entry);\n content = renderTemplate(templateContent, data);\n } else {\n content = await fs.readFile(entry, 'utf-8');\n }\n\n await writeFileSafe(targetFile, content);\n const hash = computeHash(content);\n const targetRel = path.relative(projectRoot, targetFile);\n\n results.push({\n id: `${resource.id}:${relPath}`,\n target: targetRel,\n hash,\n strategy: resource.updateStrategy,\n });\n\n logger.debug(` Written: ${targetRel}`);\n }\n\n return results;\n}\n","import * as path from 'node:path';\nimport * as fs from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport type { VariantManifest } from '@teamix-evo/registry';\nimport { loadVariantManifest } from '@teamix-evo/registry';\nimport { logger } from '../utils/logger.js';\n\nconst require = createRequire(import.meta.url);\n\n/**\n * Resolve the package root directory for a design package.\n */\nfunction resolvePackageRoot(packageName: string): string {\n const pkgJsonPath = require.resolve(`${packageName}/package.json`);\n return path.dirname(pkgJsonPath);\n}\n\n/**\n * Resolve the directory path for a variant inside a package.\n * MVP: resolves from local node_modules using require.resolve.\n *\n * @param packageName - e.g. \"@teamix-evo/tokens\"\n * @param variant - e.g. \"opentrek\"\n * @returns Absolute path to the variant directory (library/<variant>/)\n */\nexport function resolveVariantPackage(\n packageName: string,\n variant: string,\n): string {\n const pkgRoot = resolvePackageRoot(packageName);\n return path.join(pkgRoot, 'library', variant);\n}\n\n/**\n * Load the variant manifest and _data.json for template rendering.\n *\n * @param packageName - e.g. \"@teamix-evo/tokens\"\n * @param variant - e.g. \"opentrek\"\n * @returns manifest and data for template rendering\n */\nexport async function loadVariantData(\n packageName: string,\n variant: string,\n): Promise<{\n manifest: VariantManifest;\n data: Record<string, unknown>;\n variantDir: string;\n packageRoot: string;\n}> {\n const packageRoot = resolvePackageRoot(packageName);\n const variantDir = path.join(packageRoot, 'library', variant);\n\n logger.debug(`Resolved variant dir: ${variantDir}`);\n logger.debug(`Package root: ${packageRoot}`);\n\n // Load manifest\n const manifest = await loadVariantManifest(variantDir);\n\n // Load _data.json\n let data: Record<string, unknown> = {};\n const dataPath = path.join(variantDir, '_data.json');\n try {\n const raw = await fs.readFile(dataPath, 'utf-8');\n data = JSON.parse(raw) as Record<string, unknown>;\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n throw err;\n }\n logger.debug(`No _data.json found at ${dataPath}, using empty data`);\n }\n\n return { manifest, data, variantDir, packageRoot };\n}\n"],"mappings":"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","names":["path","fs","rel","path","path","fs","require","path","fs","path","os","path","fs","path","fs","createRequire","require","require","stat","rel","targetFile","newContent","exists","written","path","DEFAULT_SKILLS_PACKAGE","DEFAULT_SKILLS_PACKAGE","FLAT_VARIANT","entry","path","fs","createRequire","require","createRequire","resolvePackageRoot","path","fs","DEFAULT_UI_PACKAGE","path","createRequire","loadUiPackageManifest","require","createRequire","resolvePackageRoot","loadUiPackageManifest","mergeResources","path","fs","rel","fs","path","hasManagedRegion","replaceManagedRegion","hasManagedRegion","replaceManagedRegion","fs","path","fs","path","stat","rel","fs","path","fs","path","rel","path","path","fs","path","fs","createRequire","require","createRequire","resolvePackageRoot","resolvePackageRoot"]}
|