oh-my-customcode 1.1.100 → 1.1.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -49,7 +49,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
49
49
  // src/utils/home.ts
50
50
  import { realpathSync } from "node:fs";
51
51
  import { homedir, userInfo } from "node:os";
52
- import { isAbsolute, parse, sep } from "node:path";
52
+ import { basename, dirname, isAbsolute, join, parse, sep } from "node:path";
53
53
  function readEnvHome() {
54
54
  return process.env.HOME;
55
55
  }
@@ -99,11 +99,18 @@ function realpathOrSelf(p) {
99
99
  if (p === "" || !isAbsolute(p)) {
100
100
  return p;
101
101
  }
102
- try {
103
- return realpathSync(p);
104
- } catch {
105
- return p;
102
+ const tail = [];
103
+ let current = p;
104
+ let parent = dirname(current);
105
+ while (parent !== current) {
106
+ try {
107
+ return join(realpathSync(current), ...tail);
108
+ } catch {}
109
+ tail.unshift(basename(current));
110
+ current = parent;
111
+ parent = dirname(current);
106
112
  }
113
+ return p;
107
114
  }
108
115
  function isUnderHome(path, home) {
109
116
  const base = home ?? resolveHomeDir();
@@ -149,7 +156,7 @@ var init_home = () => {};
149
156
  import { realpathSync as realpathSync2 } from "node:fs";
150
157
  import { mkdir, readFile, writeFile } from "node:fs/promises";
151
158
  import { tmpdir } from "node:os";
152
- import { basename, join, resolve, sep as sep2 } from "node:path";
159
+ import { basename as basename2, join as join2, resolve, sep as sep2 } from "node:path";
153
160
  function isTempPath(projectPath) {
154
161
  const normalized = resolve(projectPath);
155
162
  const candidates = new Set;
@@ -184,10 +191,10 @@ function registryDir(home) {
184
191
  if (resolved === "") {
185
192
  throw new Error("Could not determine the home directory for the project registry");
186
193
  }
187
- return join(resolved, ".oh-my-customcode");
194
+ return join2(resolved, ".oh-my-customcode");
188
195
  }
189
196
  function registryPath() {
190
- return join(registryDir(), "projects.json");
197
+ return join2(registryDir(), "projects.json");
191
198
  }
192
199
  function emptyRegistry() {
193
200
  return { projects: {} };
@@ -288,14 +295,14 @@ async function migrateFromLockfiles(searchDirs) {
288
295
  } catch {
289
296
  return;
290
297
  }
291
- const entry = await parseLockFile(join(dir, ".omcustom.lock.json"));
298
+ const entry = await parseLockFile(join2(dir, ".omcustom.lock.json"));
292
299
  if (entry !== null) {
293
300
  discovered.set(resolve(dir), entry);
294
301
  return;
295
302
  }
296
303
  if (depth < MAX_DEPTH) {
297
304
  const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !SCAN_SKIP_DIRS.has(e.name));
298
- await Promise.all(subdirs.map((sub) => scan(join(dir, sub.name), depth + 1)));
305
+ await Promise.all(subdirs.map((sub) => scan(join2(dir, sub.name), depth + 1)));
299
306
  }
300
307
  }
301
308
  await Promise.all(searchDirs.map((dir) => scan(dir, 0).catch(() => {})));
@@ -328,7 +335,7 @@ var init_package = __esm(() => {
328
335
  workspaces: [
329
336
  "packages/*"
330
337
  ],
331
- version: "1.1.100",
338
+ version: "1.1.102",
332
339
  description: "Batteries-included agent harness for Claude Code",
333
340
  type: "module",
334
341
  bin: {
@@ -7324,7 +7331,7 @@ var require_public_api = __commonJS(function(exports) {
7324
7331
  });
7325
7332
 
7326
7333
  // src/utils/fs.ts
7327
- import { dirname as dirname2, isAbsolute as isAbsolute2, join as join3, relative, resolve as resolve2, sep as sep3 } from "node:path";
7334
+ import { dirname as dirname3, isAbsolute as isAbsolute3, join as join4, relative, resolve as resolve2, sep as sep3 } from "node:path";
7328
7335
  import { fileURLToPath } from "node:url";
7329
7336
  function validatePreserveFilePath(filePath, projectRoot) {
7330
7337
  if (!filePath || filePath.trim() === "") {
@@ -7333,7 +7340,7 @@ function validatePreserveFilePath(filePath, projectRoot) {
7333
7340
  reason: "Path cannot be empty"
7334
7341
  };
7335
7342
  }
7336
- if (isAbsolute2(filePath)) {
7343
+ if (isAbsolute3(filePath)) {
7337
7344
  return {
7338
7345
  valid: false,
7339
7346
  reason: "Absolute paths are not allowed"
@@ -7341,7 +7348,7 @@ function validatePreserveFilePath(filePath, projectRoot) {
7341
7348
  }
7342
7349
  const resolvedPath = resolve2(projectRoot, filePath);
7343
7350
  const relativePath = relative(projectRoot, resolvedPath);
7344
- if (relativePath.startsWith("..") || isAbsolute2(relativePath)) {
7351
+ if (relativePath.startsWith("..") || isAbsolute3(relativePath)) {
7345
7352
  return {
7346
7353
  valid: false,
7347
7354
  reason: "Path cannot traverse outside project root"
@@ -7483,17 +7490,17 @@ async function readTextFile(path) {
7483
7490
  }
7484
7491
  async function writeTextFile(path, content) {
7485
7492
  const fs = await import("node:fs/promises");
7486
- await ensureDirectory(dirname2(path));
7493
+ await ensureDirectory(dirname3(path));
7487
7494
  await fs.writeFile(path, content, "utf-8");
7488
7495
  }
7489
7496
  function getPackageRoot() {
7490
7497
  const currentFile = fileURLToPath(import.meta.url);
7491
- const currentDir = dirname2(currentFile);
7498
+ const currentDir = dirname3(currentFile);
7492
7499
  return resolve2(currentDir, "..", "..");
7493
7500
  }
7494
7501
  function resolveTemplatePath(relativePath) {
7495
7502
  const packageRoot = getPackageRoot();
7496
- return join3(packageRoot, "templates", relativePath);
7503
+ return join4(packageRoot, "templates", relativePath);
7497
7504
  }
7498
7505
  async function listFiles(dir, options = {}) {
7499
7506
  const fs = await import("node:fs/promises");
@@ -7515,7 +7522,7 @@ async function listFiles(dir, options = {}) {
7515
7522
  }
7516
7523
  async function copyFile(src, dest) {
7517
7524
  const fs = await import("node:fs/promises");
7518
- await ensureDirectory(dirname2(dest));
7525
+ await ensureDirectory(dirname3(dest));
7519
7526
  await fs.copyFile(src, dest);
7520
7527
  }
7521
7528
  async function createTempDir(prefix = "omcustom-") {
@@ -7536,9 +7543,9 @@ var UTF8_BOM = "\uFEFF";
7536
7543
  var init_fs = () => {};
7537
7544
 
7538
7545
  // src/cli/projects.ts
7539
- import { basename as basename4, join as join11, resolve as resolve3 } from "node:path";
7546
+ import { basename as basename5, join as join12, resolve as resolve3 } from "node:path";
7540
7547
  async function readLockFile(projectDir) {
7541
- const lockFilePath = join11(projectDir, ".omcustom.lock.json");
7548
+ const lockFilePath = join12(projectDir, ".omcustom.lock.json");
7542
7549
  try {
7543
7550
  const fs = await import("node:fs/promises");
7544
7551
  const content = await fs.readFile(lockFilePath, "utf-8");
@@ -7608,7 +7615,7 @@ async function findProjects(options = {}) {
7608
7615
  if (!isUnderHome(projectPath, home))
7609
7616
  continue;
7610
7617
  results.push({
7611
- name: basename4(projectPath),
7618
+ name: basename5(projectPath),
7612
7619
  path: projectPath,
7613
7620
  version: entry.version || null,
7614
7621
  installedAt: entry.installedAt || null,
@@ -7634,7 +7641,7 @@ async function _scanDirForLockfiles(dir, depth, seen, results, home, currentVers
7634
7641
  if (isUnderHome(dir, home)) {
7635
7642
  const version = lockFile.version || lockFile.templateVersion || null;
7636
7643
  results.push({
7637
- name: basename4(dir),
7644
+ name: basename5(dir),
7638
7645
  path: dir,
7639
7646
  version,
7640
7647
  installedAt: lockFile.installedAt || null,
@@ -7647,7 +7654,7 @@ async function _scanDirForLockfiles(dir, depth, seen, results, home, currentVers
7647
7654
  }
7648
7655
  if (depth < 3) {
7649
7656
  const subdirs = entries.filter((e) => e.isDirectory() && !e.name.startsWith(".") && !SCAN_SKIP_DIRS2.has(e.name));
7650
- await Promise.all(subdirs.map((sub) => _scanDirForLockfiles(join11(dir, sub.name), depth + 1, seen, results, home, currentVersion, fs).catch(() => {})));
7657
+ await Promise.all(subdirs.map((sub) => _scanDirForLockfiles(join12(dir, sub.name), depth + 1, seen, results, home, currentVersion, fs).catch(() => {})));
7651
7658
  }
7652
7659
  }
7653
7660
  async function _findProjectsFromLockfiles(options, currentVersion) {
@@ -7671,7 +7678,7 @@ async function _findProjectsFromLockfiles(options, currentVersion) {
7671
7678
  }
7672
7679
  async function writeLockFile(projectDir, version, existing) {
7673
7680
  const fs = await import("node:fs/promises");
7674
- const lockFilePath = join11(projectDir, ".omcustom.lock.json");
7681
+ const lockFilePath = join12(projectDir, ".omcustom.lock.json");
7675
7682
  const now = new Date().toISOString();
7676
7683
  const merged = {
7677
7684
  ...existing || {},
@@ -7730,7 +7737,7 @@ oh-my-customcode 적용 프로젝트 (${projects.length}개):`);
7730
7737
  현재 설치 버전: v${currentVersion}`);
7731
7738
  }
7732
7739
  function buildMigrationSearchDirs(home, extraPaths = []) {
7733
- return [...home ? DEFAULT_SEARCH_DIRS.map((d) => join11(home, d)) : [], ...extraPaths];
7740
+ return [...home ? DEFAULT_SEARCH_DIRS.map((d) => join12(home, d)) : [], ...extraPaths];
7734
7741
  }
7735
7742
  async function runMigration(options) {
7736
7743
  await Promise.resolve().then(() => init_registry());
@@ -11965,8 +11972,7 @@ init_registry();
11965
11972
  init_package();
11966
11973
  import { execSync as execSync2, spawnSync } from "node:child_process";
11967
11974
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
11968
- import { homedir as homedir2 } from "node:os";
11969
- import { dirname, join as join2 } from "node:path";
11975
+ import { dirname as dirname2, isAbsolute as isAbsolute2, join as join3 } from "node:path";
11970
11976
  import { createInterface } from "node:readline/promises";
11971
11977
 
11972
11978
  // node_modules/.bun/i18next@26.0.2+ff0372d108591aba/node_modules/i18next/dist/esm/i18next.js
@@ -14658,7 +14664,9 @@ var en_default = {
14658
14664
  openOption: "Open browser automatically after start",
14659
14665
  foregroundOption: "Run in foreground (not detached)",
14660
14666
  started: "Web UI started: http://localhost:{{port}}",
14661
- failed: "Failed to start Web UI server"
14667
+ failed: "Failed to start Web UI server",
14668
+ homeUnresolved: "Cannot start the Web UI server: the home directory cannot be resolved, either because HOME is a relative path or because HOME, the OS-reported home and the passwd entry are all empty, so the PID file location cannot be determined. Set HOME to an absolute path.",
14669
+ pidNotWritable: "Cannot start the Web UI server: the PID file {{path}} cannot be written ({{error}}). Check the PID file path and its parent directory."
14662
14670
  },
14663
14671
  stop: {
14664
14672
  description: "Stop the Web UI server",
@@ -15076,7 +15084,9 @@ var ko_default = {
15076
15084
  openOption: "시작 후 브라우저 자동 열기",
15077
15085
  foregroundOption: "포그라운드 실행 (백그라운드 분리 안 함)",
15078
15086
  started: "Web UI 시작됨: http://localhost:{{port}}",
15079
- failed: "Web UI 서버 시작 실패"
15087
+ failed: "Web UI 서버 시작 실패",
15088
+ homeUnresolved: "Web UI 서버를 시작할 수 없습니다: 홈 디렉토리를 확인할 수 없어 PID 파일 위치를 정할 수 없습니다. HOME이 상대 경로이거나, HOME·OS 보고 홈·passwd 항목이 모두 비어 있는 경우입니다. HOME을 절대 경로로 설정하세요.",
15089
+ pidNotWritable: "Web UI 서버를 시작할 수 없습니다: PID 파일 {{path}}에 쓸 수 없습니다 ({{error}}). PID 파일 경로와 그 상위 디렉토리를 확인하세요."
15080
15090
  },
15081
15091
  stop: {
15082
15092
  description: "Web UI 서버 중지",
@@ -15262,9 +15272,18 @@ var i18n = {
15262
15272
  };
15263
15273
 
15264
15274
  // src/core/self-update.ts
15275
+ init_home();
15265
15276
  var DEFAULT_PACKAGE_NAME = "oh-my-customcode";
15266
15277
  var DEFAULT_CACHE_TTL_MS = 24 * 60 * 60 * 1000;
15267
- var DEFAULT_CACHE_PATH = join2(homedir2(), ".oh-my-customcode", "self-update-cache.json");
15278
+ var CACHE_DIR_NAME = ".oh-my-customcode";
15279
+ var CACHE_FILE_NAME = "self-update-cache.json";
15280
+ function resolveSelfUpdateCachePath(sources) {
15281
+ const home = resolveHomeDir(sources);
15282
+ if (!isAbsolute2(home)) {
15283
+ return null;
15284
+ }
15285
+ return join3(home, CACHE_DIR_NAME, CACHE_FILE_NAME);
15286
+ }
15268
15287
  var MS_EPOCH_THRESHOLD = 1000000000000;
15269
15288
  function normalizeVersion(version) {
15270
15289
  return version.trim().replace(/^v/i, "").split("-")[0] || "";
@@ -15360,20 +15379,36 @@ function readSelfUpdateCache(cachePath) {
15360
15379
  }
15361
15380
  return null;
15362
15381
  }
15382
+ function readCacheAt(cachePath) {
15383
+ return cachePath === null ? null : readSelfUpdateCache(cachePath);
15384
+ }
15385
+ function isFileSystemError(error) {
15386
+ const { code, errno } = error ?? {};
15387
+ return typeof code === "string" && typeof errno === "number";
15388
+ }
15363
15389
  function writeCache(cachePath, latestVersion, now) {
15364
- const dir = dirname(cachePath);
15365
- if (!existsSync(dir)) {
15366
- mkdirSync(dir, { recursive: true });
15390
+ if (cachePath === null) {
15391
+ return;
15367
15392
  }
15368
- const payload = {
15369
- checkedAt: new Date(now).toISOString(),
15370
- latestVersion,
15371
- version: latestVersion,
15372
- timestamp: Math.floor(now / 1000),
15373
- source: "omcustom-cli"
15374
- };
15375
- writeFileSync(cachePath, `${JSON.stringify(payload, null, 2)}
15393
+ try {
15394
+ const dir = dirname2(cachePath);
15395
+ if (!existsSync(dir)) {
15396
+ mkdirSync(dir, { recursive: true });
15397
+ }
15398
+ const payload = {
15399
+ checkedAt: new Date(now).toISOString(),
15400
+ latestVersion,
15401
+ version: latestVersion,
15402
+ timestamp: Math.floor(now / 1000),
15403
+ source: "omcustom-cli"
15404
+ };
15405
+ writeFileSync(cachePath, `${JSON.stringify(payload, null, 2)}
15376
15406
  `, "utf-8");
15407
+ } catch (error) {
15408
+ if (!isFileSystemError(error)) {
15409
+ throw error;
15410
+ }
15411
+ }
15377
15412
  }
15378
15413
  function isCacheFresh(cache, now, cacheTtlMs) {
15379
15414
  const checkedAt = new Date(cache.checkedAt).getTime();
@@ -15513,7 +15548,7 @@ function executeSelfUpdate(options = {}) {
15513
15548
  }
15514
15549
  function checkSelfUpdate(options) {
15515
15550
  const packageName = options.packageName || DEFAULT_PACKAGE_NAME;
15516
- const cachePath = options.cachePath || DEFAULT_CACHE_PATH;
15551
+ const cachePath = options.cachePath || resolveSelfUpdateCachePath();
15517
15552
  const cacheTtlMs = options.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
15518
15553
  const fetchLatestVersion = options.fetchLatestVersion || fetchLatestVersionFromNpm;
15519
15554
  const now = options.now ?? Date.now();
@@ -15529,7 +15564,7 @@ function checkSelfUpdate(options) {
15529
15564
  }
15530
15565
  let latestVersion = null;
15531
15566
  let usedCache = false;
15532
- const cache = readSelfUpdateCache(cachePath);
15567
+ const cache = readCacheAt(cachePath);
15533
15568
  if (cache && isCacheFresh(cache, now, cacheTtlMs)) {
15534
15569
  const cachedVersion = normalizeVersion(cache.latestVersion);
15535
15570
  if (isVersionPlausible(currentVersion, cachedVersion)) {
@@ -16118,7 +16153,7 @@ function installCodex(deps = defaultDeps) {
16118
16153
 
16119
16154
  // src/core/config.ts
16120
16155
  init_fs();
16121
- import { join as join4 } from "node:path";
16156
+ import { join as join5 } from "node:path";
16122
16157
  var CONFIG_FILE = ".omcustomrc.json";
16123
16158
  var CURRENT_CONFIG_VERSION = 1;
16124
16159
  function getDefaultConfig() {
@@ -16158,7 +16193,7 @@ function getDefaultPreferences() {
16158
16193
  };
16159
16194
  }
16160
16195
  function getConfigPath(targetDir) {
16161
- return join4(targetDir, CONFIG_FILE);
16196
+ return join5(targetDir, CONFIG_FILE);
16162
16197
  }
16163
16198
  async function loadConfig(targetDir) {
16164
16199
  const configPath = getConfigPath(targetDir);
@@ -16256,9 +16291,9 @@ function migrateConfig(config) {
16256
16291
  // src/core/doctor-framework.ts
16257
16292
  init_fs();
16258
16293
  import { readFile as readFile2 } from "node:fs/promises";
16259
- import { join as join5 } from "node:path";
16294
+ import { join as join6 } from "node:path";
16260
16295
  async function getInstalledVersion(targetDir) {
16261
- const rcPath = join5(targetDir, ".omcustomrc.json");
16296
+ const rcPath = join6(targetDir, ".omcustomrc.json");
16262
16297
  if (!await fileExists(rcPath))
16263
16298
  return null;
16264
16299
  try {
@@ -16330,7 +16365,7 @@ init_fs();
16330
16365
  import { createHash } from "node:crypto";
16331
16366
  import { createReadStream } from "node:fs";
16332
16367
  import { readdir, stat } from "node:fs/promises";
16333
- import { join as join6, relative as relative2 } from "node:path";
16368
+ import { join as join7, relative as relative2 } from "node:path";
16334
16369
  var LOCKFILE_NAME = ".omcustom.lock.json";
16335
16370
  var LOCKFILE_VERSION = 1;
16336
16371
  var LOCKFILE_COMPONENTS = [
@@ -16359,7 +16394,7 @@ function computeFileHash(filePath) {
16359
16394
  });
16360
16395
  }
16361
16396
  async function readLockfile(targetDir) {
16362
- const lockfilePath = join6(targetDir, LOCKFILE_NAME);
16397
+ const lockfilePath = join7(targetDir, LOCKFILE_NAME);
16363
16398
  const exists = await fileExists(lockfilePath);
16364
16399
  if (!exists) {
16365
16400
  debug("lockfile.not_found", { path: lockfilePath });
@@ -16383,7 +16418,7 @@ async function readLockfile(targetDir) {
16383
16418
  }
16384
16419
  }
16385
16420
  async function writeLockfile(targetDir, lockfile) {
16386
- const lockfilePath = join6(targetDir, LOCKFILE_NAME);
16421
+ const lockfilePath = join7(targetDir, LOCKFILE_NAME);
16387
16422
  await writeJsonFile(lockfilePath, lockfile);
16388
16423
  debug("lockfile.written", { path: lockfilePath });
16389
16424
  }
@@ -16408,7 +16443,7 @@ async function collectFiles(dir, projectRoot, isTopLevel) {
16408
16443
  if (isTopLevel && entry.startsWith(".") && entry !== ".claude") {
16409
16444
  continue;
16410
16445
  }
16411
- const fullPath = join6(dir, entry);
16446
+ const fullPath = join7(dir, entry);
16412
16447
  let fileStat;
16413
16448
  try {
16414
16449
  fileStat = await stat(fullPath);
@@ -16424,9 +16459,13 @@ async function collectFiles(dir, projectRoot, isTopLevel) {
16424
16459
  }
16425
16460
  return results;
16426
16461
  }
16462
+ function sortFilesByPath(files) {
16463
+ const sorted = Object.keys(files).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
16464
+ return Object.fromEntries(sorted.map((key) => [key, files[key]]));
16465
+ }
16427
16466
  async function generateLockfile(targetDir, generatorVersion, templateVersion) {
16428
16467
  const files = {};
16429
- const componentRoots = COMPONENT_PATHS.map(([prefix]) => join6(targetDir, prefix));
16468
+ const componentRoots = COMPONENT_PATHS.map(([prefix]) => join7(targetDir, prefix));
16430
16469
  for (const componentRoot of componentRoots) {
16431
16470
  const exists = await fileExists(componentRoot);
16432
16471
  if (!exists) {
@@ -16460,15 +16499,50 @@ async function generateLockfile(targetDir, generatorVersion, templateVersion) {
16460
16499
  generatorVersion,
16461
16500
  generatedAt: new Date().toISOString(),
16462
16501
  templateVersion,
16463
- files
16502
+ files: sortFilesByPath(files)
16464
16503
  };
16465
16504
  }
16505
+ function hasSameLockfileContent(next, previous) {
16506
+ if (next.lockfileVersion !== previous.lockfileVersion || next.generatorVersion !== previous.generatorVersion || next.templateVersion !== previous.templateVersion) {
16507
+ return false;
16508
+ }
16509
+ const nextKeys = Object.keys(next.files);
16510
+ if (nextKeys.length !== Object.keys(previous.files).length) {
16511
+ return false;
16512
+ }
16513
+ return nextKeys.every((key) => {
16514
+ if (!Object.hasOwn(previous.files, key)) {
16515
+ return false;
16516
+ }
16517
+ const before = previous.files[key];
16518
+ const after = next.files[key];
16519
+ return typeof before === "object" && before !== null && before.templateHash === after.templateHash && before.size === after.size && before.component === after.component;
16520
+ });
16521
+ }
16522
+ function isIsoTimestamp(value) {
16523
+ if (typeof value !== "string") {
16524
+ return false;
16525
+ }
16526
+ const time = new Date(value).getTime();
16527
+ return !Number.isNaN(time) && new Date(time).toISOString() === value;
16528
+ }
16529
+ function preserveGeneratedAt(next, previous) {
16530
+ if (previous === null || !isIsoTimestamp(previous.generatedAt)) {
16531
+ return next;
16532
+ }
16533
+ if (!hasSameLockfileContent(next, previous)) {
16534
+ return next;
16535
+ }
16536
+ return { ...next, generatedAt: previous.generatedAt };
16537
+ }
16466
16538
  async function generateAndWriteLockfileForDir(targetDir) {
16467
16539
  try {
16468
16540
  const packageRoot = getPackageRoot();
16469
- const manifest = await readJsonFile(join6(packageRoot, "templates", "manifest.json"));
16470
- const { version: generatorVersion } = await readJsonFile(join6(packageRoot, "package.json"));
16471
- const lockfile = await generateLockfile(targetDir, generatorVersion, manifest.version);
16541
+ const manifest = await readJsonFile(join7(packageRoot, "templates", "manifest.json"));
16542
+ const { version: generatorVersion } = await readJsonFile(join7(packageRoot, "package.json"));
16543
+ const generated = await generateLockfile(targetDir, generatorVersion, manifest.version);
16544
+ const previous = await readLockfile(targetDir);
16545
+ const lockfile = preserveGeneratedAt(generated, previous);
16472
16546
  await writeLockfile(targetDir, lockfile);
16473
16547
  return { fileCount: Object.keys(lockfile.files).length };
16474
16548
  } catch (err) {
@@ -17217,7 +17291,7 @@ async function doctorCommand(options = {}) {
17217
17291
 
17218
17292
  // src/cli/init.ts
17219
17293
  init_package();
17220
- import { join as join13 } from "node:path";
17294
+ import { join as join14 } from "node:path";
17221
17295
 
17222
17296
  // src/core/installer.ts
17223
17297
  init_fs();
@@ -17228,11 +17302,11 @@ import {
17228
17302
  rename,
17229
17303
  stat as stat2
17230
17304
  } from "node:fs/promises";
17231
- import { basename as basename3, dirname as dirname4, join as join8 } from "node:path";
17305
+ import { basename as basename4, dirname as dirname5, join as join9 } from "node:path";
17232
17306
 
17233
17307
  // src/core/file-preservation.ts
17234
17308
  init_fs();
17235
- import { basename as basename2, join as join7 } from "node:path";
17309
+ import { basename as basename3, join as join8 } from "node:path";
17236
17310
 
17237
17311
  // src/core/hook-group-merge.ts
17238
17312
  var LEGACY_OMCUSTOM_DESCRIPTIONS = [
@@ -17366,8 +17440,8 @@ function matchesGlobPattern(filePath, pattern) {
17366
17440
  return regex.test(filePath);
17367
17441
  }
17368
17442
  async function extractSingleFile(fileName, rootDir, tempDir, result) {
17369
- const srcPath = join7(rootDir, fileName);
17370
- const destPath = join7(tempDir, fileName);
17443
+ const srcPath = join8(rootDir, fileName);
17444
+ const destPath = join8(tempDir, fileName);
17371
17445
  try {
17372
17446
  if (await fileExists(srcPath)) {
17373
17447
  await copyFile(srcPath, destPath);
@@ -17381,8 +17455,8 @@ async function extractSingleFile(fileName, rootDir, tempDir, result) {
17381
17455
  }
17382
17456
  }
17383
17457
  async function extractSingleDir(dirName, rootDir, tempDir, result) {
17384
- const srcPath = join7(rootDir, dirName);
17385
- const destPath = join7(tempDir, dirName);
17458
+ const srcPath = join8(rootDir, dirName);
17459
+ const destPath = join8(tempDir, dirName);
17386
17460
  try {
17387
17461
  if (await fileExists(srcPath)) {
17388
17462
  await copyDirectory(srcPath, destPath, { overwrite: true, preserveTimestamps: true });
@@ -17419,8 +17493,8 @@ async function restoreCriticalFiles(rootDir, preservation) {
17419
17493
  failures: []
17420
17494
  };
17421
17495
  for (const fileName of preservation.extractedFiles) {
17422
- const preservedPath = join7(preservation.tempDir, fileName);
17423
- const targetPath = join7(rootDir, fileName);
17496
+ const preservedPath = join8(preservation.tempDir, fileName);
17497
+ const targetPath = join8(rootDir, fileName);
17424
17498
  try {
17425
17499
  if (fileName.endsWith(".json")) {
17426
17500
  await mergeJsonFile(preservedPath, targetPath);
@@ -17436,8 +17510,8 @@ async function restoreCriticalFiles(rootDir, preservation) {
17436
17510
  }
17437
17511
  }
17438
17512
  for (const dirName of preservation.extractedDirs) {
17439
- const preservedPath = join7(preservation.tempDir, dirName);
17440
- const targetPath = join7(rootDir, dirName);
17513
+ const preservedPath = join8(preservation.tempDir, dirName);
17514
+ const targetPath = join8(rootDir, dirName);
17441
17515
  try {
17442
17516
  await copyDirectory(preservedPath, targetPath, {
17443
17517
  overwrite: false,
@@ -17462,14 +17536,14 @@ async function mergeJsonFile(preservedPath, targetPath) {
17462
17536
  if (await fileExists(targetPath)) {
17463
17537
  const { data: targetData } = parseJsonText(await readTextFile(targetPath));
17464
17538
  const merged = deepMerge(targetData, preservedData);
17465
- if (HOOKS_MERGE_FILES.has(basename2(targetPath)) && isGeneratedHookBlock(targetData.hooks)) {
17539
+ if (HOOKS_MERGE_FILES.has(basename3(targetPath)) && isGeneratedHookBlock(targetData.hooks)) {
17466
17540
  merged.hooks = mergeHookBlocks(preservedData.hooks, targetData.hooks);
17467
17541
  }
17468
17542
  await writeTextFile(targetPath, stringifyJson(merged, format));
17469
- debug("preserve.merged_json", { file: basename2(targetPath) });
17543
+ debug("preserve.merged_json", { file: basename3(targetPath) });
17470
17544
  } else {
17471
17545
  await copyFile(preservedPath, targetPath);
17472
- debug("preserve.copied_json", { file: basename2(targetPath) });
17546
+ debug("preserve.copied_json", { file: basename3(targetPath) });
17473
17547
  }
17474
17548
  }
17475
17549
  function deepMerge(target, source) {
@@ -17807,7 +17881,7 @@ function migrateHookCommands(settings) {
17807
17881
 
17808
17882
  // src/core/hooks-settings.ts
17809
17883
  init_fs();
17810
- import { dirname as dirname3 } from "node:path";
17884
+ import { dirname as dirname4 } from "node:path";
17811
17885
  var IDENT_CHAR = /[A-Za-z0-9_.]/;
17812
17886
  var IDENT_START = /[A-Za-z_]/;
17813
17887
  function consumeSingleCharOp(input, i) {
@@ -18311,7 +18385,7 @@ async function mergeHooksIntoSettings(settingsPath, hooksJsonPath, options = {})
18311
18385
  }
18312
18386
  const settings = existing.ok ? existing.settings : {};
18313
18387
  settings.hooks = preserve ? mergeHookBlocks(settings.hooks, hooks) : hooks;
18314
- await ensureDirectory(dirname3(settingsPath));
18388
+ await ensureDirectory(dirname4(settingsPath));
18315
18389
  await writeTextFile(settingsPath, stringifyJson(settings, { bom: existing.bom, trailingNewline: true }));
18316
18390
  return { warnings };
18317
18391
  }
@@ -18348,7 +18422,7 @@ function shouldInstallAgent(agentDomain, filterDomain) {
18348
18422
  var DEFAULT_LANGUAGE2 = "en";
18349
18423
  function getTemplateDir() {
18350
18424
  const packageRoot = getPackageRoot();
18351
- return join8(packageRoot, "templates");
18425
+ return join9(packageRoot, "templates");
18352
18426
  }
18353
18427
  function createInstallResult(targetDir) {
18354
18428
  return {
@@ -18370,7 +18444,7 @@ async function handleBackup(targetDir, shouldBackup, result) {
18370
18444
  if (!shouldBackup)
18371
18445
  return null;
18372
18446
  const layout = getProviderLayout();
18373
- const rootDir = join8(targetDir, layout.rootDir);
18447
+ const rootDir = join9(targetDir, layout.rootDir);
18374
18448
  let preservation = null;
18375
18449
  if (await fileExists(rootDir)) {
18376
18450
  await Promise.resolve().then(() => init_fs());
@@ -18427,8 +18501,8 @@ async function installSingleComponent(targetDir, component, options, result) {
18427
18501
  }
18428
18502
  async function installStatusline(targetDir, options, _result) {
18429
18503
  const layout = getProviderLayout();
18430
- const srcPath = resolveTemplatePath(join8(layout.rootDir, "statusline.sh"));
18431
- const destPath = join8(targetDir, layout.rootDir, "statusline.sh");
18504
+ const srcPath = resolveTemplatePath(join9(layout.rootDir, "statusline.sh"));
18505
+ const destPath = join9(targetDir, layout.rootDir, "statusline.sh");
18432
18506
  if (!await fileExists(srcPath)) {
18433
18507
  debug("install.statusline_not_found", { path: srcPath });
18434
18508
  return;
@@ -18446,9 +18520,9 @@ async function installStatusline(targetDir, options, _result) {
18446
18520
  }
18447
18521
  async function installSchemas(targetDir, options, _result) {
18448
18522
  const layout = getProviderLayout();
18449
- const relPath = join8(layout.rootDir, "schemas", "tool-inputs.json");
18523
+ const relPath = join9(layout.rootDir, "schemas", "tool-inputs.json");
18450
18524
  const srcPath = resolveTemplatePath(relPath);
18451
- const destPath = join8(targetDir, relPath);
18525
+ const destPath = join9(targetDir, relPath);
18452
18526
  if (!await fileExists(srcPath)) {
18453
18527
  debug("install.schemas_not_found", { path: srcPath });
18454
18528
  return;
@@ -18459,13 +18533,13 @@ async function installSchemas(targetDir, options, _result) {
18459
18533
  return;
18460
18534
  }
18461
18535
  }
18462
- await ensureDirectory(dirname4(destPath));
18536
+ await ensureDirectory(dirname5(destPath));
18463
18537
  await copyFile(srcPath, destPath);
18464
18538
  debug("install.schemas_installed", {});
18465
18539
  }
18466
18540
  async function installTestsConfig(targetDir, options, _result) {
18467
- const srcPath = resolveTemplatePath(join8("tests", "tsconfig.json"));
18468
- const destPath = join8(targetDir, "tests", "tsconfig.json");
18541
+ const srcPath = resolveTemplatePath(join9("tests", "tsconfig.json"));
18542
+ const destPath = join9(targetDir, "tests", "tsconfig.json");
18469
18543
  if (!await fileExists(srcPath)) {
18470
18544
  debug("install.tests_config_not_found", { path: srcPath });
18471
18545
  return;
@@ -18515,7 +18589,7 @@ async function mergeStatusLineIntoExisting(settingsPath, existing, format, defau
18515
18589
  }
18516
18590
  async function installSettingsLocal(targetDir, result) {
18517
18591
  const layout = getProviderLayout();
18518
- const settingsPath = join8(targetDir, layout.rootDir, "settings.local.json");
18592
+ const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
18519
18593
  const statusLineConfig = {
18520
18594
  statusLine: {
18521
18595
  type: "command",
@@ -18538,8 +18612,8 @@ async function installSettingsLocal(targetDir, result) {
18538
18612
  }
18539
18613
  async function installHooksSettings(targetDir, _options, result) {
18540
18614
  const layout = getProviderLayout();
18541
- const hooksJsonPath = join8(targetDir, getComponentPath("hooks"), "hooks.json");
18542
- const settingsPath = join8(targetDir, layout.rootDir, "settings.local.json");
18615
+ const hooksJsonPath = join9(targetDir, getComponentPath("hooks"), "hooks.json");
18616
+ const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
18543
18617
  if (!await fileExists(hooksJsonPath)) {
18544
18618
  debug("install.hooks_settings_skipped", { reason: "hooks.json not installed" });
18545
18619
  return;
@@ -18561,7 +18635,7 @@ async function installHooksSettings(targetDir, _options, result) {
18561
18635
  var BOM = "\uFEFF";
18562
18636
  async function migrateRestoredHookCommands(targetDir, result) {
18563
18637
  const layout = getProviderLayout();
18564
- const settingsPath = join8(targetDir, layout.rootDir, "settings.local.json");
18638
+ const settingsPath = join9(targetDir, layout.rootDir, "settings.local.json");
18565
18639
  if (!await fileExists(settingsPath)) {
18566
18640
  return;
18567
18641
  }
@@ -18647,7 +18721,7 @@ async function install(options) {
18647
18721
  await installEntryDocWithTracking(options.targetDir, options, result);
18648
18722
  if (preservation) {
18649
18723
  const layout = getProviderLayout();
18650
- const rootDir = join8(options.targetDir, layout.rootDir);
18724
+ const rootDir = join9(options.targetDir, layout.rootDir);
18651
18725
  const restoration = await restoreCriticalFiles(rootDir, preservation);
18652
18726
  if (restoration.restoredFiles.length > 0 || restoration.restoredDirs.length > 0) {
18653
18727
  info("install.restored", {
@@ -18685,7 +18759,7 @@ async function install(options) {
18685
18759
  async function getTemplateManifest() {
18686
18760
  const packageRoot = getPackageRoot();
18687
18761
  const layout = getProviderLayout();
18688
- const manifestPath = join8(packageRoot, "templates", layout.manifestFile);
18762
+ const manifestPath = join9(packageRoot, "templates", layout.manifestFile);
18689
18763
  if (await fileExists(manifestPath)) {
18690
18764
  return readJsonFile(manifestPath);
18691
18765
  }
@@ -18708,10 +18782,10 @@ async function installSkillsWithScopeFilter(srcPath, destPath, options) {
18708
18782
  await ensureDirectory(destPath);
18709
18783
  const entries = await readdir2(srcPath);
18710
18784
  for (const entry of entries) {
18711
- const entrySrcPath = join8(srcPath, entry);
18785
+ const entrySrcPath = join9(srcPath, entry);
18712
18786
  if (!(await stat2(entrySrcPath)).isDirectory())
18713
18787
  continue;
18714
- const skillMdPath = join8(entrySrcPath, "SKILL.md");
18788
+ const skillMdPath = join9(entrySrcPath, "SKILL.md");
18715
18789
  if (await fileExists(skillMdPath)) {
18716
18790
  const content = await fsReadFile(skillMdPath, "utf-8");
18717
18791
  const scope = getSkillScope(content);
@@ -18720,7 +18794,7 @@ async function installSkillsWithScopeFilter(srcPath, destPath, options) {
18720
18794
  continue;
18721
18795
  }
18722
18796
  }
18723
- await copyDirectory(entrySrcPath, join8(destPath, entry), {
18797
+ await copyDirectory(entrySrcPath, join9(destPath, entry), {
18724
18798
  overwrite: !!(options.force || options.backup),
18725
18799
  preserveSymlinks: true,
18726
18800
  preserveTimestamps: true
@@ -18731,10 +18805,10 @@ async function installAgentsWithDomainFilter(srcPath, destPath, options) {
18731
18805
  await ensureDirectory(destPath);
18732
18806
  const entries = await readdir2(srcPath);
18733
18807
  for (const entry of entries) {
18734
- const entrySrcPath = join8(srcPath, entry);
18808
+ const entrySrcPath = join9(srcPath, entry);
18735
18809
  const entryStat = await stat2(entrySrcPath);
18736
18810
  if (entryStat.isDirectory()) {
18737
- await copyDirectory(entrySrcPath, join8(destPath, entry), {
18811
+ await copyDirectory(entrySrcPath, join9(destPath, entry), {
18738
18812
  overwrite: !!(options.force || options.backup),
18739
18813
  preserveSymlinks: true,
18740
18814
  preserveTimestamps: true
@@ -18751,7 +18825,7 @@ async function installAgentsWithDomainFilter(srcPath, destPath, options) {
18751
18825
  continue;
18752
18826
  }
18753
18827
  }
18754
- await copyFile(entrySrcPath, join8(destPath, entry));
18828
+ await copyFile(entrySrcPath, join9(destPath, entry));
18755
18829
  }
18756
18830
  }
18757
18831
  async function installComponent(targetDir, component, options) {
@@ -18759,7 +18833,7 @@ async function installComponent(targetDir, component, options) {
18759
18833
  return false;
18760
18834
  }
18761
18835
  const templatePath = getComponentPath(component);
18762
- const destPath = join8(targetDir, templatePath);
18836
+ const destPath = join9(targetDir, templatePath);
18763
18837
  const destExists = await fileExists(destPath);
18764
18838
  if (destExists && !options.force && !options.backup) {
18765
18839
  debug("install.component_skipped", { component });
@@ -18793,7 +18867,7 @@ async function installEntryDoc(targetDir, language, overwrite = false) {
18793
18867
  const layout = getProviderLayout();
18794
18868
  const templateFile = getEntryTemplateName(language);
18795
18869
  const srcPath = resolveTemplatePath(templateFile);
18796
- const destPath = join8(targetDir, layout.entryFile);
18870
+ const destPath = join9(targetDir, layout.entryFile);
18797
18871
  if (!await fileExists(srcPath)) {
18798
18872
  warn("install.entry_md_not_found", { language, path: srcPath, entry: layout.entryFile });
18799
18873
  return false;
@@ -18813,8 +18887,8 @@ async function installEntryDoc(targetDir, language, overwrite = false) {
18813
18887
  return true;
18814
18888
  }
18815
18889
  async function backupExisting(sourcePath, backupDir) {
18816
- const name = basename3(sourcePath);
18817
- const backupPath = join8(backupDir, name);
18890
+ const name = basename4(sourcePath);
18891
+ const backupPath = join9(backupDir, name);
18818
18892
  await rename(sourcePath, backupPath);
18819
18893
  return backupPath;
18820
18894
  }
@@ -18823,7 +18897,7 @@ async function checkExistingPaths(targetDir) {
18823
18897
  const pathsToCheck = [layout.entryFile, layout.rootDir, "guides"];
18824
18898
  const existingPaths = [];
18825
18899
  for (const relativePath of pathsToCheck) {
18826
- const fullPath = join8(targetDir, relativePath);
18900
+ const fullPath = join9(targetDir, relativePath);
18827
18901
  if (await fileExists(fullPath)) {
18828
18902
  existingPaths.push(relativePath);
18829
18903
  }
@@ -18837,11 +18911,11 @@ async function backupExistingInstallation(targetDir) {
18837
18911
  return [];
18838
18912
  }
18839
18913
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
18840
- const backupDir = join8(targetDir, `${layout.backupDirPrefix}${timestamp}`);
18914
+ const backupDir = join9(targetDir, `${layout.backupDirPrefix}${timestamp}`);
18841
18915
  await ensureDirectory(backupDir);
18842
18916
  const backedUpPaths = [];
18843
18917
  for (const relativePath of existingPaths) {
18844
- const fullPath = join8(targetDir, relativePath);
18918
+ const fullPath = join9(targetDir, relativePath);
18845
18919
  try {
18846
18920
  const backupPath = await backupExisting(fullPath, backupDir);
18847
18921
  backedUpPaths.push(backupPath);
@@ -18857,12 +18931,12 @@ async function backupExistingInstallation(targetDir) {
18857
18931
  // src/core/mcp-config.ts
18858
18932
  init_fs();
18859
18933
  import { writeFile as writeFile2 } from "node:fs/promises";
18860
- import { join as join9 } from "node:path";
18934
+ import { join as join10 } from "node:path";
18861
18935
  async function generateMCPConfig(targetDir) {
18862
18936
  const layout = getProviderLayout();
18863
- const mcpConfigPath = join9(targetDir, ".mcp.json");
18864
- const ontologyDir = join9(layout.rootDir, "ontology");
18865
- const ontologyExists = await fileExists(join9(targetDir, ontologyDir));
18937
+ const mcpConfigPath = join10(targetDir, ".mcp.json");
18938
+ const ontologyDir = join10(layout.rootDir, "ontology");
18939
+ const ontologyExists = await fileExists(join10(targetDir, ontologyDir));
18866
18940
  if (!ontologyExists) {
18867
18941
  return;
18868
18942
  }
@@ -18904,7 +18978,7 @@ async function generateMCPConfig(targetDir) {
18904
18978
  // src/core/ontology-rag-setup.ts
18905
18979
  init_fs();
18906
18980
  import { execSync as execSync5 } from "node:child_process";
18907
- import { join as join10 } from "node:path";
18981
+ import { join as join11 } from "node:path";
18908
18982
  var MIN_PYTHON_MINOR = 10;
18909
18983
  var DETECTION_TIMEOUT_MS = 3000;
18910
18984
  var INSTALL_TIMEOUT_MS = 90000;
@@ -18955,7 +19029,7 @@ function createVenvWithPython3(targetDir) {
18955
19029
  }
18956
19030
  function installOntologyRagEditable(targetDir, useUv) {
18957
19031
  const packageRoot = getPackageRoot();
18958
- const ontologyPkgPath = join10(packageRoot, "packages", "ontology-rag");
19032
+ const ontologyPkgPath = join11(packageRoot, "packages", "ontology-rag");
18959
19033
  if (useUv) {
18960
19034
  execSync5(`uv pip install --python .venv/bin/python -e "${ontologyPkgPath}"`, {
18961
19035
  cwd: targetDir,
@@ -19028,7 +19102,7 @@ async function setupOntologyRag(targetDir) {
19028
19102
  reason
19029
19103
  };
19030
19104
  }
19031
- const venvPython = join10(targetDir, ".venv", "bin", "python");
19105
+ const venvPython = join11(targetDir, ".venv", "bin", "python");
19032
19106
  const venvReady = await fileExists(venvPython);
19033
19107
  if (!venvReady) {
19034
19108
  const reason = ".venv/bin/python missing after install — environment may be incomplete. " + "Run `uv pip install -e packages/ontology-rag` manually to complete setup.";
@@ -19054,12 +19128,12 @@ init_package();
19054
19128
  init_projects();
19055
19129
  import { existsSync as existsSync2 } from "node:fs";
19056
19130
  import { copyFile as copyFile2, cp } from "node:fs/promises";
19057
- import { join as join12 } from "node:path";
19131
+ import { join as join13 } from "node:path";
19058
19132
  init_fs();
19059
19133
  init_registry();
19060
19134
  async function checkExistingInstallation(targetDir) {
19061
19135
  const layout = getProviderLayout();
19062
- const rootDir = join12(targetDir, layout.rootDir);
19136
+ const rootDir = join13(targetDir, layout.rootDir);
19063
19137
  return fileExists(rootDir);
19064
19138
  }
19065
19139
  async function installFromSnapshot(targetDir, snapshotPath, options) {
@@ -19071,7 +19145,7 @@ async function installFromSnapshot(targetDir, snapshotPath, options) {
19071
19145
  };
19072
19146
  }
19073
19147
  const layout = getProviderLayout();
19074
- const snapshotClaude = join12(snapshotPath, layout.rootDir);
19148
+ const snapshotClaude = join13(snapshotPath, layout.rootDir);
19075
19149
  if (!existsSync2(snapshotClaude)) {
19076
19150
  return {
19077
19151
  success: false,
@@ -19085,24 +19159,24 @@ async function installFromSnapshot(targetDir, snapshotPath, options) {
19085
19159
  if (exists && !options.force) {
19086
19160
  console.log(i18n.t("cli.init.exists", { rootDir: layout.rootDir }));
19087
19161
  console.log(i18n.t("cli.init.backing_up"));
19088
- const backupDir = join12(targetDir, `.claude-backup-${new Date().toISOString().replace(/[:.]/g, "-").slice(0, -1)}`);
19089
- await cp(join12(targetDir, layout.rootDir), backupDir, { recursive: true });
19162
+ const backupDir = join13(targetDir, `.claude-backup-${new Date().toISOString().replace(/[:.]/g, "-").slice(0, -1)}`);
19163
+ await cp(join13(targetDir, layout.rootDir), backupDir, { recursive: true });
19090
19164
  console.log(` Backed up to: ${backupDir}`);
19091
19165
  }
19092
- await cp(snapshotClaude, join12(targetDir, layout.rootDir), {
19166
+ await cp(snapshotClaude, join13(targetDir, layout.rootDir), {
19093
19167
  recursive: true,
19094
19168
  force: true
19095
19169
  });
19096
- const snapshotGuides = join12(snapshotPath, "guides");
19170
+ const snapshotGuides = join13(snapshotPath, "guides");
19097
19171
  if (existsSync2(snapshotGuides)) {
19098
- await cp(snapshotGuides, join12(targetDir, "guides"), {
19172
+ await cp(snapshotGuides, join13(targetDir, "guides"), {
19099
19173
  recursive: true,
19100
19174
  force: true
19101
19175
  });
19102
19176
  }
19103
- const snapshotEntry = join12(snapshotPath, layout.entryFile);
19177
+ const snapshotEntry = join13(snapshotPath, layout.entryFile);
19104
19178
  if (existsSync2(snapshotEntry)) {
19105
- await copyFile2(snapshotEntry, join12(targetDir, layout.entryFile));
19179
+ await copyFile2(snapshotEntry, join13(targetDir, layout.entryFile));
19106
19180
  }
19107
19181
  try {
19108
19182
  const existing = await readLockFile(targetDir);
@@ -19985,7 +20059,7 @@ async function runInitWizard(options) {
19985
20059
  // src/cli/init.ts
19986
20060
  async function checkExistingInstallation2(targetDir) {
19987
20061
  const layout = getProviderLayout();
19988
- const rootDir = join13(targetDir, layout.rootDir);
20062
+ const rootDir = join14(targetDir, layout.rootDir);
19989
20063
  return fileExists(rootDir);
19990
20064
  }
19991
20065
  var PROVIDER_SUBDIR_COMPONENTS = new Set([
@@ -19999,13 +20073,13 @@ var PROVIDER_SUBDIR_COMPONENTS = new Set([
19999
20073
  function componentToPath(targetDir, component) {
20000
20074
  if (component === "entry-md") {
20001
20075
  const layout = getProviderLayout();
20002
- return join13(targetDir, layout.entryFile);
20076
+ return join14(targetDir, layout.entryFile);
20003
20077
  }
20004
20078
  if (PROVIDER_SUBDIR_COMPONENTS.has(component)) {
20005
20079
  const layout = getProviderLayout();
20006
- return join13(targetDir, layout.rootDir, component);
20080
+ return join14(targetDir, layout.rootDir, component);
20007
20081
  }
20008
- return join13(targetDir, component);
20082
+ return join14(targetDir, component);
20009
20083
  }
20010
20084
  function buildInstalledPaths(targetDir, components) {
20011
20085
  return components.map((component) => componentToPath(targetDir, component));
@@ -20128,7 +20202,7 @@ async function initCommand(options) {
20128
20202
  }
20129
20203
 
20130
20204
  // src/cli/list.ts
20131
- import { basename as basename5, dirname as dirname5, join as join14, relative as relative3 } from "node:path";
20205
+ import { basename as basename6, dirname as dirname6, join as join15, relative as relative3 } from "node:path";
20132
20206
  init_fs();
20133
20207
  var ALLOWED_TOP_LEVEL_KEYS = new Set(["name", "type", "description", "version", "category"]);
20134
20208
  function parseKeyValue(line) {
@@ -20175,7 +20249,7 @@ function parseYamlMetadata(content) {
20175
20249
  return result;
20176
20250
  }
20177
20251
  function extractAgentTypeFromFilename(filename) {
20178
- const name = basename5(filename, ".md");
20252
+ const name = basename6(filename, ".md");
20179
20253
  const prefixMap = {
20180
20254
  lang: "language",
20181
20255
  be: "backend",
@@ -20193,17 +20267,17 @@ function extractAgentTypeFromFilename(filename) {
20193
20267
  return prefixMap[prefix] || "unknown";
20194
20268
  }
20195
20269
  function extractSkillCategoryFromPath(skillPath, baseDir, rootDir) {
20196
- const relativePath = relative3(join14(baseDir, rootDir, "skills"), skillPath);
20270
+ const relativePath = relative3(join15(baseDir, rootDir, "skills"), skillPath);
20197
20271
  const parts = relativePath.split("/").filter(Boolean);
20198
20272
  return parts[0] || "unknown";
20199
20273
  }
20200
20274
  function extractGuideCategoryFromPath(guidePath, baseDir) {
20201
- const relativePath = relative3(join14(baseDir, "guides"), guidePath);
20275
+ const relativePath = relative3(join15(baseDir, "guides"), guidePath);
20202
20276
  const parts = relativePath.split("/").filter(Boolean);
20203
20277
  return parts[0] || "unknown";
20204
20278
  }
20205
20279
  function extractRulePriorityFromFilename(filename) {
20206
- const name = basename5(filename, ".md");
20280
+ const name = basename6(filename, ".md");
20207
20281
  const parts = name.split("-");
20208
20282
  return parts[0] || "unknown";
20209
20283
  }
@@ -20292,7 +20366,7 @@ async function tryExtractMarkdownDescription(mdPath, options = {}) {
20292
20366
  }
20293
20367
  }
20294
20368
  async function getAgents(targetDir, rootDir = ".claude", config) {
20295
- const agentsDir = join14(targetDir, rootDir, "agents");
20369
+ const agentsDir = join15(targetDir, rootDir, "agents");
20296
20370
  if (!await fileExists(agentsDir))
20297
20371
  return [];
20298
20372
  try {
@@ -20301,8 +20375,8 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
20301
20375
  const customAgentPaths = new Set(customComponents.filter((c) => c.type === "agent").map((c) => c.path));
20302
20376
  const agentMdFiles = await listFiles(agentsDir, { recursive: false, pattern: "*.md" });
20303
20377
  const agents = await Promise.all(agentMdFiles.map(async (agentMdPath) => {
20304
- const filename = basename5(agentMdPath);
20305
- const name = basename5(filename, ".md");
20378
+ const filename = basename6(agentMdPath);
20379
+ const name = basename6(filename, ".md");
20306
20380
  const description = await tryExtractMarkdownDescription(agentMdPath);
20307
20381
  const relativePath = relative3(targetDir, agentMdPath);
20308
20382
  return {
@@ -20320,7 +20394,7 @@ async function getAgents(targetDir, rootDir = ".claude", config) {
20320
20394
  }
20321
20395
  }
20322
20396
  async function getSkills(targetDir, rootDir = ".claude", config) {
20323
- const skillsDir = join14(targetDir, rootDir, "skills");
20397
+ const skillsDir = join15(targetDir, rootDir, "skills");
20324
20398
  if (!await fileExists(skillsDir))
20325
20399
  return [];
20326
20400
  try {
@@ -20329,12 +20403,12 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
20329
20403
  const customSkillPaths = new Set(customComponents.filter((c) => c.type === "skill").map((c) => c.path));
20330
20404
  const skillMdFiles = await listFiles(skillsDir, { recursive: true, pattern: "SKILL.md" });
20331
20405
  const skills = await Promise.all(skillMdFiles.map(async (skillMdPath) => {
20332
- const skillDir = dirname5(skillMdPath);
20333
- const indexYamlPath = join14(skillDir, "index.yaml");
20406
+ const skillDir = dirname6(skillMdPath);
20407
+ const indexYamlPath = join15(skillDir, "index.yaml");
20334
20408
  const { description, version } = await tryReadIndexYamlMetadata(indexYamlPath);
20335
20409
  const relativePath = relative3(targetDir, skillDir);
20336
20410
  return {
20337
- name: basename5(skillDir),
20411
+ name: basename6(skillDir),
20338
20412
  type: "skill",
20339
20413
  category: extractSkillCategoryFromPath(skillDir, targetDir, rootDir),
20340
20414
  path: relativePath,
@@ -20349,7 +20423,7 @@ async function getSkills(targetDir, rootDir = ".claude", config) {
20349
20423
  }
20350
20424
  }
20351
20425
  async function getGuides(targetDir, config) {
20352
- const guidesDir = join14(targetDir, "guides");
20426
+ const guidesDir = join15(targetDir, "guides");
20353
20427
  if (!await fileExists(guidesDir))
20354
20428
  return [];
20355
20429
  try {
@@ -20361,7 +20435,7 @@ async function getGuides(targetDir, config) {
20361
20435
  const description = await tryExtractMarkdownDescription(guideMdPath, { maxLength: 100 });
20362
20436
  const relativePath = relative3(targetDir, guideMdPath);
20363
20437
  return {
20364
- name: basename5(guideMdPath, ".md"),
20438
+ name: basename6(guideMdPath, ".md"),
20365
20439
  type: "guide",
20366
20440
  category: extractGuideCategoryFromPath(guideMdPath, targetDir),
20367
20441
  path: relativePath,
@@ -20376,7 +20450,7 @@ async function getGuides(targetDir, config) {
20376
20450
  }
20377
20451
  var RULE_PRIORITY_ORDER = { MUST: 0, SHOULD: 1, MAY: 2 };
20378
20452
  async function getRules(targetDir, rootDir = ".claude", config) {
20379
- const rulesDir = join14(targetDir, rootDir, "rules");
20453
+ const rulesDir = join15(targetDir, rootDir, "rules");
20380
20454
  if (!await fileExists(rulesDir))
20381
20455
  return [];
20382
20456
  try {
@@ -20385,13 +20459,13 @@ async function getRules(targetDir, rootDir = ".claude", config) {
20385
20459
  const customRulePaths = new Set(customComponents.filter((c) => c.type === "rule").map((c) => c.path));
20386
20460
  const ruleMdFiles = await listFiles(rulesDir, { recursive: false, pattern: "*.md" });
20387
20461
  const rules = await Promise.all(ruleMdFiles.map(async (ruleMdPath) => {
20388
- const filename = basename5(ruleMdPath);
20462
+ const filename = basename6(ruleMdPath);
20389
20463
  const description = await tryExtractMarkdownDescription(ruleMdPath, {
20390
20464
  cleanFormatting: true
20391
20465
  });
20392
20466
  const relativePath = relative3(targetDir, ruleMdPath);
20393
20467
  return {
20394
- name: basename5(ruleMdPath, ".md"),
20468
+ name: basename6(ruleMdPath, ".md"),
20395
20469
  type: extractRulePriorityFromFilename(filename),
20396
20470
  path: relativePath,
20397
20471
  description,
@@ -20448,7 +20522,7 @@ function formatAsJson(components) {
20448
20522
  console.log(JSON.stringify(components, null, 2));
20449
20523
  }
20450
20524
  async function getHooks(targetDir, rootDir = ".claude") {
20451
- const hooksDir = join14(targetDir, rootDir, "hooks");
20525
+ const hooksDir = join15(targetDir, rootDir, "hooks");
20452
20526
  if (!await fileExists(hooksDir))
20453
20527
  return [];
20454
20528
  try {
@@ -20457,7 +20531,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
20457
20531
  const hookYamls = await listFiles(hooksDir, { recursive: true, pattern: "*.yaml" });
20458
20532
  const allFiles = [...hookFiles, ...hookConfigs, ...hookYamls];
20459
20533
  return allFiles.map((hookPath) => ({
20460
- name: basename5(hookPath),
20534
+ name: basename6(hookPath),
20461
20535
  type: "hook",
20462
20536
  path: relative3(targetDir, hookPath)
20463
20537
  })).sort((a, b) => a.name.localeCompare(b.name));
@@ -20466,7 +20540,7 @@ async function getHooks(targetDir, rootDir = ".claude") {
20466
20540
  }
20467
20541
  }
20468
20542
  async function getContexts(targetDir, rootDir = ".claude") {
20469
- const contextsDir = join14(targetDir, rootDir, "contexts");
20543
+ const contextsDir = join15(targetDir, rootDir, "contexts");
20470
20544
  if (!await fileExists(contextsDir))
20471
20545
  return [];
20472
20546
  try {
@@ -20477,7 +20551,7 @@ async function getContexts(targetDir, rootDir = ".claude") {
20477
20551
  const ext = ctxPath.endsWith(".md") ? ".md" : ".yaml";
20478
20552
  const description = ext === ".md" ? await tryExtractMarkdownDescription(ctxPath, { maxLength: 100 }) : undefined;
20479
20553
  return {
20480
- name: basename5(ctxPath, ext),
20554
+ name: basename6(ctxPath, ext),
20481
20555
  type: "context",
20482
20556
  path: relative3(targetDir, ctxPath),
20483
20557
  description
@@ -20859,50 +20933,85 @@ async function securityCommand(_options = {}) {
20859
20933
 
20860
20934
  // src/cli/serve-commands.ts
20861
20935
  import { spawnSync as spawnSync2 } from "node:child_process";
20862
- import { join as join16 } from "node:path";
20936
+ import { join as join17 } from "node:path";
20863
20937
 
20864
20938
  // src/cli/serve.ts
20939
+ init_home();
20865
20940
  import { spawn } from "node:child_process";
20866
- import { existsSync as existsSync3 } from "node:fs";
20867
- import { readFile as readFile3, unlink, writeFile as writeFile3 } from "node:fs/promises";
20868
- import { join as join15 } from "node:path";
20941
+ import { constants as constants3, existsSync as existsSync3 } from "node:fs";
20942
+ import { access, readFile as readFile3, unlink, writeFile as writeFile3 } from "node:fs/promises";
20943
+ import { dirname as dirname7, isAbsolute as isAbsolute4, join as join16 } from "node:path";
20869
20944
  var DEFAULT_PORT = 4321;
20870
- var PID_FILE = join15(process.env.HOME ?? "~", ".omcustom-serve.pid");
20945
+ var PID_FILE_NAME = ".omcustom-serve.pid";
20946
+
20947
+ class ServePidFileError extends Error {
20948
+ reason;
20949
+ pidFile;
20950
+ constructor(reason, pidFile, options) {
20951
+ super(reason === "home-unresolved" ? "Cannot resolve the serve PID file: the home directory is empty or relative" : `Cannot write the serve PID file: ${pidFile}`, options);
20952
+ this.name = "ServePidFileError";
20953
+ this.reason = reason;
20954
+ this.pidFile = pidFile;
20955
+ }
20956
+ }
20957
+ function resolveServePidFile(sources) {
20958
+ const home = resolveHomeDir(sources);
20959
+ if (!isAbsolute4(home)) {
20960
+ return null;
20961
+ }
20962
+ return join16(home, PID_FILE_NAME);
20963
+ }
20871
20964
  function findServeBuildDir(projectRoot, options) {
20872
- const localBuild = join15(projectRoot, "packages", "serve", "build");
20873
- if (existsSync3(join15(localBuild, "index.js")))
20965
+ const localBuild = join16(projectRoot, "packages", "serve", "build");
20966
+ if (existsSync3(join16(localBuild, "index.js")))
20874
20967
  return localBuild;
20875
20968
  if (options?.skipNpmFallback !== true) {
20876
- const npmBuild = join15(import.meta.dirname, "..", "..", "packages", "serve", "build");
20877
- if (existsSync3(join15(npmBuild, "index.js")))
20969
+ const npmBuild = join16(import.meta.dirname, "..", "..", "packages", "serve", "build");
20970
+ if (existsSync3(join16(npmBuild, "index.js")))
20878
20971
  return npmBuild;
20879
20972
  }
20880
20973
  return null;
20881
20974
  }
20882
20975
  async function isServeRunning() {
20976
+ const pidFile = resolveServePidFile();
20977
+ if (pidFile === null) {
20978
+ return false;
20979
+ }
20980
+ return isServeRunningAt(pidFile);
20981
+ }
20982
+ async function isServeRunningAt(pidFile) {
20883
20983
  try {
20884
- const raw = await readFile3(PID_FILE, "utf-8");
20984
+ const raw = await readFile3(pidFile, "utf-8");
20885
20985
  const pid = Number(raw.trim());
20886
20986
  if (!Number.isFinite(pid) || pid <= 0) {
20887
- await cleanupPidFile();
20987
+ await cleanupPidFile(pidFile);
20888
20988
  return false;
20889
20989
  }
20890
20990
  process.kill(pid, 0);
20891
20991
  return true;
20892
20992
  } catch {
20893
- await cleanupPidFile();
20993
+ await cleanupPidFile(pidFile);
20894
20994
  return false;
20895
20995
  }
20896
20996
  }
20897
20997
  async function startServeBackground(projectRoot, port = DEFAULT_PORT, buildDirOpts) {
20898
- if (await isServeRunning()) {
20998
+ const pidFile = resolveServePidFile();
20999
+ if (pidFile === null) {
21000
+ throw new ServePidFileError("home-unresolved", null);
21001
+ }
21002
+ if (await isServeRunningAt(pidFile)) {
20899
21003
  return;
20900
21004
  }
20901
21005
  const buildDir = findServeBuildDir(projectRoot, buildDirOpts);
20902
21006
  if (buildDir === null) {
20903
21007
  return;
20904
21008
  }
20905
- const child = spawn("node", [join15(buildDir, "index.js")], {
21009
+ try {
21010
+ await access(dirname7(pidFile), constants3.W_OK);
21011
+ } catch (error) {
21012
+ throw new ServePidFileError("pid-not-writable", pidFile, { cause: error });
21013
+ }
21014
+ const child = spawn("node", [join16(buildDir, "index.js")], {
20906
21015
  env: {
20907
21016
  ...process.env,
20908
21017
  OMCUSTOM_PORT: String(port),
@@ -20913,30 +21022,41 @@ async function startServeBackground(projectRoot, port = DEFAULT_PORT, buildDirOp
20913
21022
  stdio: "ignore",
20914
21023
  detached: true
20915
21024
  });
21025
+ child.on("error", () => {});
20916
21026
  child.unref();
20917
- if (child.pid !== undefined) {
20918
- await writeFile3(PID_FILE, String(child.pid), "utf-8");
21027
+ if (child.pid === undefined) {
21028
+ return;
21029
+ }
21030
+ try {
21031
+ await writeFile3(pidFile, String(child.pid), "utf-8");
21032
+ } catch (error) {
21033
+ child.kill("SIGTERM");
21034
+ throw new ServePidFileError("pid-not-writable", pidFile, { cause: error });
20919
21035
  }
20920
21036
  }
20921
21037
  async function stopServe() {
21038
+ const pidFile = resolveServePidFile();
21039
+ if (pidFile === null) {
21040
+ return false;
21041
+ }
20922
21042
  try {
20923
- const raw = await readFile3(PID_FILE, "utf-8");
21043
+ const raw = await readFile3(pidFile, "utf-8");
20924
21044
  const pid = Number(raw.trim());
20925
21045
  if (!Number.isFinite(pid) || pid <= 0) {
20926
- await cleanupPidFile();
21046
+ await cleanupPidFile(pidFile);
20927
21047
  return false;
20928
21048
  }
20929
21049
  process.kill(pid, "SIGTERM");
20930
- await cleanupPidFile();
21050
+ await cleanupPidFile(pidFile);
20931
21051
  return true;
20932
21052
  } catch {
20933
- await cleanupPidFile();
21053
+ await cleanupPidFile(pidFile);
20934
21054
  return false;
20935
21055
  }
20936
21056
  }
20937
- async function cleanupPidFile() {
21057
+ async function cleanupPidFile(pidFile) {
20938
21058
  try {
20939
- await unlink(PID_FILE);
21059
+ await unlink(pidFile);
20940
21060
  } catch {}
20941
21061
  }
20942
21062
 
@@ -20955,7 +21075,15 @@ async function serveCommand(options) {
20955
21075
  runForeground(cwd, port, buildDirOpts);
20956
21076
  return;
20957
21077
  }
20958
- await startServeBackground(cwd, port, buildDirOpts);
21078
+ try {
21079
+ await startServeBackground(cwd, port, buildDirOpts);
21080
+ } catch (error) {
21081
+ if (!(error instanceof ServePidFileError)) {
21082
+ throw error;
21083
+ }
21084
+ console.error(describePidFileError(error));
21085
+ process.exit(1);
21086
+ }
20959
21087
  const running = await isServeRunning();
20960
21088
  if (running) {
20961
21089
  console.log(i18n.t("cli.web.start.started", { port }));
@@ -20964,6 +21092,13 @@ async function serveCommand(options) {
20964
21092
  process.exit(1);
20965
21093
  }
20966
21094
  }
21095
+ function describePidFileError(error) {
21096
+ if (error.reason === "home-unresolved") {
21097
+ return i18n.t("cli.web.start.homeUnresolved");
21098
+ }
21099
+ const cause = error.cause instanceof Error ? error.cause.message : String(error.cause);
21100
+ return i18n.t("cli.web.start.pidNotWritable", { path: String(error.pidFile), error: cause });
21101
+ }
20967
21102
  async function serveStopCommand() {
20968
21103
  const stopped = await stopServe();
20969
21104
  if (stopped) {
@@ -20979,7 +21114,7 @@ function runForeground(projectRoot, port, buildDirOpts) {
20979
21114
  process.exit(1);
20980
21115
  }
20981
21116
  console.log(`Web UI: http://localhost:${port}`);
20982
- spawnSync2("node", [join16(buildDir, "index.js")], {
21117
+ spawnSync2("node", [join17(buildDir, "index.js")], {
20983
21118
  env: {
20984
21119
  ...process.env,
20985
21120
  OMCUSTOM_PORT: String(port),
@@ -20998,12 +21133,12 @@ import { resolve as resolve4 } from "node:path";
20998
21133
  init_fs();
20999
21134
  import { existsSync as existsSync4 } from "node:fs";
21000
21135
  import { cp as cp2, mkdir as mkdir2 } from "node:fs/promises";
21001
- import { join as join17 } from "node:path";
21136
+ import { join as join18 } from "node:path";
21002
21137
  async function loadVersions() {
21003
21138
  try {
21004
21139
  const packageRoot = getPackageRoot();
21005
- const manifest = await readJsonFile(join17(packageRoot, "templates", "manifest.json"));
21006
- const pkg = await readJsonFile(join17(packageRoot, "package.json"));
21140
+ const manifest = await readJsonFile(join18(packageRoot, "templates", "manifest.json"));
21141
+ const pkg = await readJsonFile(join18(packageRoot, "package.json"));
21007
21142
  return { generatorVersion: pkg.version, templateVersion: manifest.version };
21008
21143
  } catch {
21009
21144
  return { generatorVersion: "0.0.0", templateVersion: "0.0.0" };
@@ -21073,7 +21208,7 @@ async function countFiles(dir) {
21073
21208
  return 0;
21074
21209
  }
21075
21210
  for (const entry of entries) {
21076
- const full = join17(current, entry);
21211
+ const full = join18(current, entry);
21077
21212
  try {
21078
21213
  const s = await stat(full);
21079
21214
  if (s.isDirectory()) {
@@ -21088,19 +21223,19 @@ async function countFiles(dir) {
21088
21223
  return walk(dir);
21089
21224
  }
21090
21225
  async function exportSnapshot(targetDir, outputPath) {
21091
- const claudeDir = join17(targetDir, ".claude");
21092
- const guidesDir = join17(targetDir, "guides");
21226
+ const claudeDir = join18(targetDir, ".claude");
21227
+ const guidesDir = join18(targetDir, "guides");
21093
21228
  if (!existsSync4(claudeDir)) {
21094
21229
  return { success: false, exportPath: outputPath, fileCount: 0 };
21095
21230
  }
21096
21231
  await mkdir2(outputPath, { recursive: true });
21097
- const destClaude = join17(outputPath, ".claude");
21232
+ const destClaude = join18(outputPath, ".claude");
21098
21233
  await cp2(claudeDir, destClaude, {
21099
21234
  recursive: true,
21100
21235
  filter: isExportable
21101
21236
  });
21102
21237
  if (existsSync4(guidesDir)) {
21103
- await cp2(guidesDir, join17(outputPath, "guides"), { recursive: true });
21238
+ await cp2(guidesDir, join18(outputPath, "guides"), { recursive: true });
21104
21239
  }
21105
21240
  const lockfile = await generateCurrentLockfile(targetDir);
21106
21241
  if (lockfile) {
@@ -21184,7 +21319,7 @@ import { constants as osConstants } from "node:os";
21184
21319
 
21185
21320
  // src/core/updater.ts
21186
21321
  init_package();
21187
- import { join as join18 } from "node:path";
21322
+ import { join as join19 } from "node:path";
21188
21323
  init_fs();
21189
21324
 
21190
21325
  // src/core/entry-merger.ts
@@ -21439,7 +21574,7 @@ function resolveCustomizations(customizations, configPreserveFiles, targetDir) {
21439
21574
  }
21440
21575
  async function updateEntryDoc(targetDir, config, options) {
21441
21576
  const layout = getProviderLayout();
21442
- const entryPath = join18(targetDir, layout.entryFile);
21577
+ const entryPath = join19(targetDir, layout.entryFile);
21443
21578
  const templateName = getEntryTemplateName2(config.language);
21444
21579
  const templatePath = resolveTemplatePath(templateName);
21445
21580
  if (!await fileExists(templatePath)) {
@@ -21477,7 +21612,7 @@ async function backfillStatusLineRefreshInterval(targetDir, options) {
21477
21612
  return;
21478
21613
  }
21479
21614
  const layout = getProviderLayout();
21480
- const settingsPath = join18(targetDir, layout.rootDir, "settings.local.json");
21615
+ const settingsPath = join19(targetDir, layout.rootDir, "settings.local.json");
21481
21616
  if (!await fileExists(settingsPath)) {
21482
21617
  return;
21483
21618
  }
@@ -21503,7 +21638,7 @@ async function migrateHookCommandsInSettingsLocal(targetDir, options) {
21503
21638
  return;
21504
21639
  }
21505
21640
  const layout = getProviderLayout();
21506
- const settingsPath = join18(targetDir, layout.rootDir, "settings.local.json");
21641
+ const settingsPath = join19(targetDir, layout.rootDir, "settings.local.json");
21507
21642
  if (!await fileExists(settingsPath)) {
21508
21643
  return;
21509
21644
  }
@@ -21598,7 +21733,7 @@ async function regenerateLockfile(targetDir, result) {
21598
21733
  }
21599
21734
  }
21600
21735
  async function shouldSkipSelfUpdate2(targetDir, result) {
21601
- const targetPkgPath = join18(targetDir, "package.json");
21736
+ const targetPkgPath = join19(targetDir, "package.json");
21602
21737
  if (await fileExists(targetPkgPath)) {
21603
21738
  const targetPkg = await readJsonFile(targetPkgPath);
21604
21739
  if (targetPkg.name === "oh-my-customcode") {
@@ -21737,11 +21872,11 @@ async function collectProtectedSkipPaths(srcPath, destPath, componentPath, force
21737
21872
  const warnedPaths = [];
21738
21873
  const updatedPaths = [];
21739
21874
  for (const p of protectedRelative) {
21740
- const targetFilePath = join18(targetDir, componentPath, p);
21875
+ const targetFilePath = join19(targetDir, componentPath, p);
21741
21876
  const lockfileKey = `${componentPath}/${p}`.replace(/\\/g, "/");
21742
21877
  const shouldSkip = await shouldSkipProtectedFile(targetFilePath, lockfileKey, lockfile);
21743
21878
  if (shouldSkip) {
21744
- skipPaths.push(path.relative(destPath, join18(destPath, p)));
21879
+ skipPaths.push(path.relative(destPath, join19(destPath, p)));
21745
21880
  warnedPaths.push(p);
21746
21881
  } else {
21747
21882
  updatedPaths.push(p);
@@ -21787,7 +21922,7 @@ async function updateComponent(targetDir, component, customizations, options, co
21787
21922
  const preservedFiles = [];
21788
21923
  const componentPath = getComponentPath2(component);
21789
21924
  const srcPath = resolveTemplatePath(componentPath);
21790
- const destPath = join18(targetDir, componentPath);
21925
+ const destPath = join19(targetDir, componentPath);
21791
21926
  const customComponents = config.customComponents || [];
21792
21927
  const skipPaths = [];
21793
21928
  if (customizations && !options.forceOverwriteAll) {
@@ -21829,7 +21964,7 @@ async function updateComponent(targetDir, component, customizations, options, co
21829
21964
  }
21830
21965
  skipPaths.push(...protectedSkipPaths);
21831
21966
  const path = await import("node:path");
21832
- const normalizedSkipPaths = skipPaths.map((p) => path.relative(destPath, join18(targetDir, p)));
21967
+ const normalizedSkipPaths = skipPaths.map((p) => path.relative(destPath, join19(targetDir, p)));
21833
21968
  const uniqueSkipPaths = [...new Set(normalizedSkipPaths)];
21834
21969
  await copyDirectory(srcPath, destPath, {
21835
21970
  overwrite: true,
@@ -21858,7 +21993,7 @@ async function syncRootLevelFiles(targetDir, options, customizations) {
21858
21993
  const preserved = [];
21859
21994
  const preserveSet = new Set(customizations && !options.forceOverwriteAll ? customizations.preserveFiles : []);
21860
21995
  for (const fileName of ROOT_LEVEL_FILES) {
21861
- const srcPath = resolveTemplatePath(join18(layout.rootDir, fileName));
21996
+ const srcPath = resolveTemplatePath(join19(layout.rootDir, fileName));
21862
21997
  if (!await fileExists(srcPath)) {
21863
21998
  continue;
21864
21999
  }
@@ -21867,8 +22002,8 @@ async function syncRootLevelFiles(targetDir, options, customizations) {
21867
22002
  preserved.push(relPath);
21868
22003
  continue;
21869
22004
  }
21870
- const destPath = join18(targetDir, layout.rootDir, fileName);
21871
- await ensureDirectory(join18(destPath, ".."));
22005
+ const destPath = join19(targetDir, layout.rootDir, fileName);
22006
+ await ensureDirectory(join19(destPath, ".."));
21872
22007
  await fs.copyFile(srcPath, destPath);
21873
22008
  if (fileName.endsWith(".sh")) {
21874
22009
  await fs.chmod(destPath, 493);
@@ -21903,7 +22038,7 @@ async function removeDeprecatedFiles(targetDir, options) {
21903
22038
  });
21904
22039
  continue;
21905
22040
  }
21906
- const fullPath = join18(targetDir, entry.path);
22041
+ const fullPath = join19(targetDir, entry.path);
21907
22042
  if (await fileExists(fullPath)) {
21908
22043
  await fs.unlink(fullPath);
21909
22044
  removed.push(entry.path);
@@ -21944,7 +22079,7 @@ async function syncNamespaceInFile(targetFilePath, upstreamFilePath) {
21944
22079
  async function processNamespaceSyncEntry(entry, relPath, fullSrcPath, destPath, componentPath, lockfile) {
21945
22080
  if (!entry.isFile() || !entry.name.endsWith(".md"))
21946
22081
  return null;
21947
- const targetFilePath = join18(destPath, relPath);
22082
+ const targetFilePath = join19(destPath, relPath);
21948
22083
  const lockfileKey = `${componentPath}/${relPath}`.replace(/\\/g, "/");
21949
22084
  const shouldSkip = await shouldSkipProtectedFile(targetFilePath, lockfileKey, lockfile);
21950
22085
  if (shouldSkip)
@@ -21959,7 +22094,7 @@ async function applyNamespaceSync(targetDir, component, lockfile) {
21959
22094
  return [];
21960
22095
  const componentPath = getComponentPath2(component);
21961
22096
  const srcPath = resolveTemplatePath(componentPath);
21962
- const destPath = join18(targetDir, componentPath);
22097
+ const destPath = join19(targetDir, componentPath);
21963
22098
  const fs = await import("node:fs/promises");
21964
22099
  const synced = [];
21965
22100
  const queue = [{ dir: srcPath, relDir: "" }];
@@ -21973,7 +22108,7 @@ async function applyNamespaceSync(targetDir, component, lockfile) {
21973
22108
  }
21974
22109
  for (const entry of entries) {
21975
22110
  const relPath = relDir ? `${relDir}/${entry.name}` : entry.name;
21976
- const fullSrcPath = join18(dir, entry.name);
22111
+ const fullSrcPath = join19(dir, entry.name);
21977
22112
  if (entry.isDirectory()) {
21978
22113
  queue.push({ dir: fullSrcPath, relDir: relPath });
21979
22114
  continue;
@@ -21996,26 +22131,26 @@ function getComponentPath2(component) {
21996
22131
  }
21997
22132
  async function backupInstallation(targetDir) {
21998
22133
  const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
21999
- const backupDir = join18(targetDir, `.omcustom-backup-${timestamp}`);
22134
+ const backupDir = join19(targetDir, `.omcustom-backup-${timestamp}`);
22000
22135
  const fs = await import("node:fs/promises");
22001
22136
  await ensureDirectory(backupDir);
22002
22137
  const layout = getProviderLayout();
22003
22138
  const dirsToBackup = [layout.rootDir, "guides"];
22004
22139
  for (const dir of dirsToBackup) {
22005
- const srcPath = join18(targetDir, dir);
22140
+ const srcPath = join19(targetDir, dir);
22006
22141
  if (await fileExists(srcPath)) {
22007
- const destPath = join18(backupDir, dir);
22142
+ const destPath = join19(backupDir, dir);
22008
22143
  await copyDirectory(srcPath, destPath, { overwrite: true });
22009
22144
  }
22010
22145
  }
22011
- const entryPath = join18(targetDir, layout.entryFile);
22146
+ const entryPath = join19(targetDir, layout.entryFile);
22012
22147
  if (await fileExists(entryPath)) {
22013
- await fs.copyFile(entryPath, join18(backupDir, layout.entryFile));
22148
+ await fs.copyFile(entryPath, join19(backupDir, layout.entryFile));
22014
22149
  }
22015
22150
  return backupDir;
22016
22151
  }
22017
22152
  async function loadCustomizationManifest(targetDir) {
22018
- const manifestPath = join18(targetDir, CUSTOMIZATION_MANIFEST_FILE);
22153
+ const manifestPath = join19(targetDir, CUSTOMIZATION_MANIFEST_FILE);
22019
22154
  if (await fileExists(manifestPath)) {
22020
22155
  return readJsonFile(manifestPath);
22021
22156
  }