claude-nomad 0.67.1 → 0.67.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/nomad.mjs CHANGED
@@ -806,12 +806,12 @@ import {
806
806
  cpSync as cpSync3,
807
807
  existsSync as existsSync3,
808
808
  fsyncSync,
809
- lstatSync as lstatSync4,
809
+ lstatSync as lstatSync5,
810
810
  mkdirSync,
811
811
  openSync,
812
812
  renameSync,
813
813
  rmdirSync,
814
- statSync,
814
+ statSync as statSync2,
815
815
  symlinkSync,
816
816
  writeFileSync
817
817
  } from "node:fs";
@@ -840,7 +840,7 @@ function renameAtomicRetry(tmp, dst, renameFn = renameSync) {
840
840
  }
841
841
  }
842
842
  function writeJsonAtomic(path, data) {
843
- const mode = existsSync3(path) ? statSync(path).mode & 511 : 384;
843
+ const mode = existsSync3(path) ? statSync2(path).mode & 511 : 384;
844
844
  const tmp = `${path}.tmp.${process.pid}`;
845
845
  const fd = openSync(tmp, "w", mode);
846
846
  try {
@@ -879,7 +879,7 @@ function discardEmptyBackupDir(backupRoot) {
879
879
  }
880
880
  function ensureSymlink(linkPath, target) {
881
881
  if (existsSync3(linkPath)) {
882
- if (lstatSync4(linkPath).isSymbolicLink()) return;
882
+ if (lstatSync5(linkPath).isSymbolicLink()) return;
883
883
  die(`${linkPath} exists and is not a symlink. Move it aside first.`);
884
884
  }
885
885
  mkdirSync(dirname(linkPath), { recursive: true });
@@ -918,12 +918,12 @@ var init_utils_fs = __esm({
918
918
 
919
919
  // src/commands.pull.wedge.ts
920
920
  import { execFileSync as execFileSync3 } from "node:child_process";
921
- import { existsSync as existsSync16 } from "node:fs";
922
- import { join as join20 } from "node:path";
921
+ import { existsSync as existsSync15 } from "node:fs";
922
+ import { join as join21 } from "node:path";
923
923
  function detectWedge(repo) {
924
- const g = join20(repo, ".git");
925
- if (existsSync16(join20(g, "rebase-merge")) || existsSync16(join20(g, "rebase-apply"))) return "rebase";
926
- if (existsSync16(join20(g, "MERGE_HEAD"))) return "merge";
924
+ const g = join21(repo, ".git");
925
+ if (existsSync15(join21(g, "rebase-merge")) || existsSync15(join21(g, "rebase-apply"))) return "rebase";
926
+ if (existsSync15(join21(g, "MERGE_HEAD"))) return "merge";
927
927
  return null;
928
928
  }
929
929
  function probeUnmergedIndex(repo) {
@@ -993,15 +993,15 @@ var init_commands_pull_wedge = __esm({
993
993
  });
994
994
 
995
995
  // src/push-gitleaks.config.ts
996
- import { existsSync as existsSync17, mkdtempSync, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
996
+ import { existsSync as existsSync16, mkdtempSync, readFileSync as readFileSync5, writeFileSync as writeFileSync3 } from "node:fs";
997
997
  import { tmpdir } from "node:os";
998
- import { join as join21 } from "node:path";
998
+ import { join as join22 } from "node:path";
999
999
  import { fileURLToPath } from "node:url";
1000
1000
  function resolveTomlPath(repo = repoHome()) {
1001
- const repoToml = join21(repo, ".gitleaks.toml");
1002
- if (existsSync17(repoToml)) return repoToml;
1001
+ const repoToml = join22(repo, ".gitleaks.toml");
1002
+ if (existsSync16(repoToml)) return repoToml;
1003
1003
  const bundled = fileURLToPath(new URL("../.gitleaks.toml", import.meta.url));
1004
- return existsSync17(bundled) ? bundled : null;
1004
+ return existsSync16(bundled) ? bundled : null;
1005
1005
  }
1006
1006
  function assertOverlayAllowlistsScoped(overlayBody) {
1007
1007
  if (OVERLAY_INLINE_ALLOWLIST_RE.test(overlayBody)) {
@@ -1039,17 +1039,17 @@ function buildOverlayTempConfig(overlayBody, bundled) {
1039
1039
  path = ${JSON.stringify(bundled)}
1040
1040
 
1041
1041
  ${overlayBody}`;
1042
- const tempPath = mkdtempSync(join21(tmpdir(), "nomad-gitleaks-cfg-"));
1043
- const configPath = join21(tempPath, "config.toml");
1042
+ const tempPath = mkdtempSync(join22(tmpdir(), "nomad-gitleaks-cfg-"));
1043
+ const configPath = join22(tempPath, "config.toml");
1044
1044
  writeFileSync3(configPath, tempBody, { mode: 384, flag: "wx" });
1045
1045
  return { configPath, tempPath };
1046
1046
  }
1047
1047
  function resolveTomlConfig() {
1048
1048
  const repo = repoHome();
1049
- const overlayPath = join21(repo, ".gitleaks.overlay.toml");
1050
- const repoToml = join21(repo, ".gitleaks.toml");
1049
+ const overlayPath = join22(repo, ".gitleaks.overlay.toml");
1050
+ const repoToml = join22(repo, ".gitleaks.toml");
1051
1051
  const bundled = resolveTomlPath(repo);
1052
- if (!existsSync17(overlayPath)) {
1052
+ if (!existsSync16(overlayPath)) {
1053
1053
  return { path: bundled, tempPath: null };
1054
1054
  }
1055
1055
  if (bundled === repoToml) {
@@ -1137,7 +1137,7 @@ var init_autostash_guard = __esm({
1137
1137
  import { execFileSync as execFileSync4 } from "node:child_process";
1138
1138
  import { readdirSync as readdirSync8, rmSync as rmSync7 } from "node:fs";
1139
1139
  import { homedir as homedir2, platform } from "node:os";
1140
- import { delimiter, join as join22 } from "node:path";
1140
+ import { delimiter, join as join23 } from "node:path";
1141
1141
  function gitleaksInstallHint() {
1142
1142
  const head = "gitleaks not on PATH (required for nomad push). Install:";
1143
1143
  const plat = platform();
@@ -1185,7 +1185,7 @@ function findGitlinks(dir) {
1185
1185
  return;
1186
1186
  }
1187
1187
  for (const e of entries) {
1188
- const p = join22(current, e.name);
1188
+ const p = join23(current, e.name);
1189
1189
  if (e.name === ".git") {
1190
1190
  hits.push(p);
1191
1191
  continue;
@@ -1249,7 +1249,7 @@ var init_push_checks = __esm({
1249
1249
  import { execFileSync as execFileSync8 } from "node:child_process";
1250
1250
  import { mkdirSync as mkdirSync3, mkdtempSync as mkdtempSync2, readFileSync as readFileSync6, rmSync as rmSync8 } from "node:fs";
1251
1251
  import { homedir as homedir3 } from "node:os";
1252
- import { join as join26 } from "node:path";
1252
+ import { join as join27 } from "node:path";
1253
1253
  function toFinding(entry) {
1254
1254
  if (typeof entry !== "object" || entry === null) return null;
1255
1255
  const e = entry;
@@ -1297,9 +1297,9 @@ function resolveScanFailure(reportPath, e, forwardStreams) {
1297
1297
  return report;
1298
1298
  }
1299
1299
  function scanStagedTree(repoDir, forwardStreams = false) {
1300
- const cacheDir = join26(homedir3(), ".cache", "claude-nomad");
1300
+ const cacheDir = join27(homedir3(), ".cache", "claude-nomad");
1301
1301
  mkdirSync3(cacheDir, { recursive: true });
1302
- const reportPath = join26(cacheDir, `gitleaks-${nowTimestamp()}-${process.pid}.json`);
1302
+ const reportPath = join27(cacheDir, `gitleaks-${nowTimestamp()}-${process.pid}.json`);
1303
1303
  const { path: toml, tempPath } = resolveTomlConfig();
1304
1304
  const args = [
1305
1305
  "protect",
@@ -1327,14 +1327,14 @@ function scanStagedTree(repoDir, forwardStreams = false) {
1327
1327
  }
1328
1328
  }
1329
1329
  function scanFile(filePath, forwardStreams = false, timeoutMs = GITLEAKS_SCAN_TIMEOUT_MS) {
1330
- const cacheDir = join26(homedir3(), ".cache", "claude-nomad");
1330
+ const cacheDir = join27(homedir3(), ".cache", "claude-nomad");
1331
1331
  mkdirSync3(cacheDir, { recursive: true });
1332
1332
  const { path: toml, tempPath } = resolveTomlConfig();
1333
1333
  let reportDir;
1334
1334
  let reportPath;
1335
1335
  try {
1336
- reportDir = mkdtempSync2(join26(cacheDir, `gitleaks-file-${nowTimestamp()}-${process.pid}-`));
1337
- reportPath = join26(reportDir, "report.json");
1336
+ reportDir = mkdtempSync2(join27(cacheDir, `gitleaks-file-${nowTimestamp()}-${process.pid}-`));
1337
+ reportPath = join27(reportDir, "report.json");
1338
1338
  const args = [
1339
1339
  "detect",
1340
1340
  "--no-git",
@@ -1562,7 +1562,7 @@ import { existsSync as existsSync5, lstatSync as lstatSync7 } from "node:fs";
1562
1562
  import { join as join9 } from "node:path";
1563
1563
 
1564
1564
  // src/commands.adopt.recover.ts
1565
- import { lstatSync as lstatSync6, rmSync as rmSync4 } from "node:fs";
1565
+ import { rmSync as rmSync4 } from "node:fs";
1566
1566
  import { dirname as dirname2, join as join7, resolve as resolve2 } from "node:path";
1567
1567
 
1568
1568
  // src/commands.adopt.scan.ts
@@ -1872,9 +1872,34 @@ function copyExtrasFilteredPreserving(src, dst, blockSet) {
1872
1872
  });
1873
1873
  }
1874
1874
 
1875
+ // src/fs-presence.ts
1876
+ import { lstatSync as lstatSync4, statSync } from "node:fs";
1877
+ var ABSENT_CODES = /* @__PURE__ */ new Set(["ENOENT", "ENOTDIR", "ENAMETOOLONG"]);
1878
+ function classifyPresence(p) {
1879
+ let stat;
1880
+ try {
1881
+ stat = lstatSync4(p, { throwIfNoEntry: false });
1882
+ } catch (err) {
1883
+ return ABSENT_CODES.has(String(err.code)) ? "absent" : "unknown";
1884
+ }
1885
+ if (stat === void 0) return "absent";
1886
+ try {
1887
+ statSync(p);
1888
+ } catch (err) {
1889
+ return ABSENT_CODES.has(String(err.code)) ? "dangling" : "unknown";
1890
+ }
1891
+ return "resolves";
1892
+ }
1893
+ function isUnusableTarget(state) {
1894
+ return state === "dangling" || state === "unknown";
1895
+ }
1896
+ function lexists(p) {
1897
+ return classifyPresence(p) !== "absent";
1898
+ }
1899
+
1875
1900
  // src/links.ts
1876
1901
  init_config();
1877
- import { existsSync as existsSync4, lstatSync as lstatSync5, rmSync as rmSync3 } from "node:fs";
1902
+ import { existsSync as existsSync4, lstatSync as lstatSync6, rmSync as rmSync3 } from "node:fs";
1878
1903
  import { join as join6 } from "node:path";
1879
1904
 
1880
1905
  // src/hooks-filter.ts
@@ -2190,14 +2215,14 @@ function emitCopy(onPreview, from, to) {
2190
2215
  }
2191
2216
  }
2192
2217
  function isAlreadySymlink(linkPath) {
2193
- return existsSync4(linkPath) && lstatSync5(linkPath).isSymbolicLink();
2218
+ return existsSync4(linkPath) && lstatSync6(linkPath).isSymbolicLink();
2194
2219
  }
2195
2220
  function runAutoMovePasses(linkNames, claude, repo, ts, dryRun, onPreview) {
2196
2221
  for (const name of linkNames) {
2197
2222
  const linkPath = join6(claude, name);
2198
2223
  const target = join6(repo, "shared", name);
2199
2224
  if (!existsSync4(linkPath)) continue;
2200
- if (lstatSync5(linkPath).isSymbolicLink()) continue;
2225
+ if (lstatSync6(linkPath).isSymbolicLink()) continue;
2201
2226
  if (!existsSync4(target)) continue;
2202
2227
  if (dryRun) {
2203
2228
  emitAutoMove(onPreview, linkPath, ts, name);
@@ -2212,7 +2237,7 @@ function copySharedLinkPull(src, dst) {
2212
2237
  }
2213
2238
  function stillOccupied(abs) {
2214
2239
  try {
2215
- return lstatSync5(abs, { throwIfNoEntry: false }) !== void 0;
2240
+ return lstatSync6(abs, { throwIfNoEntry: false }) !== void 0;
2216
2241
  } catch {
2217
2242
  return true;
2218
2243
  }
@@ -2237,7 +2262,7 @@ function warnWin32ApplyFailed(linkPath, ts, err, snapshotted) {
2237
2262
  function applyOneSharedLinkWin32(target, linkPath, ts) {
2238
2263
  let snapshotted = false;
2239
2264
  try {
2240
- const stat = lstatSync5(linkPath, { throwIfNoEntry: false });
2265
+ const stat = lstatSync6(linkPath, { throwIfNoEntry: false });
2241
2266
  if (stat !== void 0) {
2242
2267
  const snapshot = snapshotBeforeWin32Copy(linkPath, ts);
2243
2268
  if (snapshot === "failed") return;
@@ -2352,14 +2377,6 @@ function regenerateSettings(ts, opts = {}) {
2352
2377
 
2353
2378
  // src/commands.adopt.recover.ts
2354
2379
  init_utils();
2355
- function lexists(p) {
2356
- try {
2357
- lstatSync6(p);
2358
- return true;
2359
- } catch {
2360
- return false;
2361
- }
2362
- }
2363
2380
  function isDirectChildOf(root, abs) {
2364
2381
  return dirname2(resolve2(abs)) === resolve2(root);
2365
2382
  }
@@ -2604,11 +2621,56 @@ function isValidAdoptName(name) {
2604
2621
  if (SHARED_LINKS.includes(name)) return true;
2605
2622
  return isValidSharedDir(name);
2606
2623
  }
2624
+ function refuseUnusableSharedTarget(name) {
2625
+ throw new NomadFatal(
2626
+ `${name}: shared/${name} does not resolve to anything usable, so adopting would publish nothing. Remove shared/${name} from the repo, or restore what it points at, then re-run adopt.`,
2627
+ { code: EXIT.GENERIC_FAILURE }
2628
+ );
2629
+ }
2630
+ function clobberMessage(name, state) {
2631
+ if (state === "dangling") {
2632
+ return `${name}: shared/${name} is a pointer that does not resolve; would clobber. Remove it, or restore what it points at, first.`;
2633
+ }
2634
+ if (state === "unknown") {
2635
+ return `${name}: shared/${name} could not be read, so adopt cannot tell whether it would clobber existing content. Check its permissions in the sync repo.`;
2636
+ }
2637
+ return `${name}: shared/${name} already exists; would clobber. Remove it first.`;
2638
+ }
2639
+ function refuseClobber(name, sharedTarget) {
2640
+ const state = classifyPresence(sharedTarget);
2641
+ if (state === "absent") return;
2642
+ throw new NomadFatal(clobberMessage(name, state), { code: EXIT.GENERIC_FAILURE });
2643
+ }
2607
2644
  function reportWin32AlreadyAdopted(name, sharedTarget) {
2608
- if (process.platform !== "win32" || !lexists(sharedTarget)) return false;
2645
+ if (process.platform !== "win32") return false;
2646
+ const state = classifyPresence(sharedTarget);
2647
+ if (state === "absent") return false;
2648
+ if (isUnusableTarget(state)) refuseUnusableSharedTarget(name);
2609
2649
  log(`${name}: already adopted (win32 copy-sync); run \`nomad pull\` to refresh the local copy`);
2610
2650
  return true;
2611
2651
  }
2652
+ function alreadySymlinkMessage(name, sharedTarget) {
2653
+ const state = classifyPresence(sharedTarget);
2654
+ if (state === "dangling") {
2655
+ return {
2656
+ text: `${name}: already a symlink, but shared/${name} does not resolve, so the link is broken. Restore shared/${name} in the repo, or remove ~/.claude/${name} and re-run adopt`,
2657
+ healthy: false
2658
+ };
2659
+ }
2660
+ if (state === "unknown") {
2661
+ return {
2662
+ text: `${name}: already a symlink, but shared/${name} could not be read, so whether the link works could not be determined. Check its permissions in the sync repo`,
2663
+ healthy: false
2664
+ };
2665
+ }
2666
+ if (state === "absent") {
2667
+ return {
2668
+ text: `${name}: already a symlink, but there is no shared/${name} in the repo, so it is not adopted. Remove ~/.claude/${name} and re-run adopt, or run \`nomad pull\` if another host shares it`,
2669
+ healthy: false
2670
+ };
2671
+ }
2672
+ return { text: `${name}: already adopted (already a symlink)`, healthy: true };
2673
+ }
2612
2674
  function adoptStopsEarly(name, linkPath, sharedTarget) {
2613
2675
  if (!existsSync5(linkPath)) {
2614
2676
  if (reportWin32AlreadyAdopted(name, sharedTarget)) return true;
@@ -2616,14 +2678,13 @@ function adoptStopsEarly(name, linkPath, sharedTarget) {
2616
2678
  return true;
2617
2679
  }
2618
2680
  if (lstatSync7(linkPath).isSymbolicLink()) {
2619
- log(`${name}: already adopted (already a symlink)`);
2681
+ const { text, healthy } = alreadySymlinkMessage(name, sharedTarget);
2682
+ if (healthy) log(text);
2683
+ else warn(text);
2620
2684
  return true;
2621
2685
  }
2622
2686
  if (reportWin32AlreadyAdopted(name, sharedTarget)) return true;
2623
- if (lexists(sharedTarget)) {
2624
- fail(`${name}: shared/${name} already exists; would clobber. Remove it first.`);
2625
- process.exit(1);
2626
- }
2687
+ refuseClobber(name, sharedTarget);
2627
2688
  return false;
2628
2689
  }
2629
2690
  function performAdoptMove(name, linkPath, sharedTarget, repo, backup) {
@@ -2656,18 +2717,19 @@ function cmdAdopt(name, opts = {}) {
2656
2717
  );
2657
2718
  }
2658
2719
  if (!isValidAdoptName(name)) {
2659
- fail(`invalid name: ${JSON.stringify(name)}`);
2660
- process.exit(1);
2720
+ throw new NomadFatal(`invalid name: ${JSON.stringify(name)}`, {
2721
+ code: EXIT.GENERIC_FAILURE
2722
+ });
2661
2723
  }
2662
2724
  const repo = repoHome();
2663
2725
  const claude = claudeHome();
2664
2726
  const backup = backupBase();
2665
2727
  const map = readMapIfPresent(repo);
2666
2728
  if (!isConfiguredTarget(name, map)) {
2667
- fail(
2668
- `${name}: not a configured shared target. Add it to sharedDirs in path-map.json first, then re-run adopt.`
2729
+ throw new NomadFatal(
2730
+ `${name}: not a configured shared target. Add it to sharedDirs in path-map.json first, then re-run adopt.`,
2731
+ { code: EXIT.GENERIC_FAILURE }
2669
2732
  );
2670
- process.exit(1);
2671
2733
  }
2672
2734
  const linkPath = join9(claude, name);
2673
2735
  const sharedTarget = join9(repo, "shared", name);
@@ -2889,7 +2951,7 @@ async function cmdCaptureSettings(opts) {
2889
2951
  init_config();
2890
2952
  init_exit_codes();
2891
2953
  init_utils();
2892
- import { existsSync as existsSync8, lstatSync as lstatSync8, readdirSync as readdirSync4, rmSync as rmSync5, statSync as statSync2 } from "node:fs";
2954
+ import { existsSync as existsSync8, lstatSync as lstatSync8, readdirSync as readdirSync4, rmSync as rmSync5, statSync as statSync3 } from "node:fs";
2893
2955
  import { join as join12 } from "node:path";
2894
2956
  var TS_SHAPE = /^\d{8}-\d{6}(-\d+)?$/;
2895
2957
  var DURATION_RE = /^(\d+)([dhm])$/;
@@ -2908,7 +2970,7 @@ function parseDuration(s) {
2908
2970
  }
2909
2971
  function listBackupDirs(backupBase2) {
2910
2972
  if (!existsSync8(backupBase2)) return [];
2911
- return readdirSync4(backupBase2).filter(isTsDir).map((name) => ({ name, mtimeMs: statSync2(join12(backupBase2, name)).mtimeMs })).sort((a, b) => b.mtimeMs - a.mtimeMs);
2973
+ return readdirSync4(backupBase2).filter(isTsDir).map((name) => ({ name, mtimeMs: statSync3(join12(backupBase2, name)).mtimeMs })).sort((a, b) => b.mtimeMs - a.mtimeMs);
2912
2974
  }
2913
2975
  function holdsNoContent(dir) {
2914
2976
  let entries;
@@ -3189,14 +3251,14 @@ function cmdEject(opts = {}, roots = defaultEjectRoots()) {
3189
3251
  }
3190
3252
 
3191
3253
  // src/commands.doctor.ts
3192
- import { existsSync as existsSync36 } from "node:fs";
3193
- import { join as join48 } from "node:path";
3254
+ import { existsSync as existsSync35 } from "node:fs";
3255
+ import { join as join49 } from "node:path";
3194
3256
 
3195
3257
  // src/commands.doctor.checks.repo.ts
3196
3258
  init_color();
3197
3259
  init_config();
3198
- import { existsSync as existsSync12, lstatSync as lstatSync10, readdirSync as readdirSync5, statSync as statSync3 } from "node:fs";
3199
- import { join as join16 } from "node:path";
3260
+ import { existsSync as existsSync11, lstatSync as lstatSync10, readdirSync as readdirSync5, statSync as statSync4 } from "node:fs";
3261
+ import { join as join17 } from "node:path";
3200
3262
 
3201
3263
  // src/commands.doctor.format.ts
3202
3264
  init_color();
@@ -3274,7 +3336,6 @@ function readJsonSafe(path, label, section2) {
3274
3336
  // src/commands.doctor.checks.repo.win32.ts
3275
3337
  init_color();
3276
3338
  init_config();
3277
- import { existsSync as existsSync10 } from "node:fs";
3278
3339
  import { join as join14, win32 as win32Path } from "node:path";
3279
3340
 
3280
3341
  // src/extras-sync.diff.ts
@@ -3343,6 +3404,18 @@ function win32CopyUnpublishedRow(name) {
3343
3404
  fail: false
3344
3405
  };
3345
3406
  }
3407
+ function win32CopyUnusableRow(name, state) {
3408
+ if (state === "dangling") {
3409
+ return {
3410
+ line: `${yellow(warnGlyph)} ${name}: real local copy, but shared/${name} does not resolve in the repo (remove shared/${name}, or restore what it points at)`,
3411
+ fail: false
3412
+ };
3413
+ }
3414
+ return {
3415
+ line: `${yellow(warnGlyph)} ${name}: real local copy, but shared/${name} could not be read in the repo, so whether it is usable could not be determined (check its permissions in the sync repo)`,
3416
+ fail: false
3417
+ };
3418
+ }
3346
3419
  function relativeUnder(root, path) {
3347
3420
  const rel = win32Path.relative(root, path);
3348
3421
  const segments = rel.split(win32Path.sep);
@@ -3356,7 +3429,9 @@ function divergingRepoPath(line, name, local, shared) {
3356
3429
  }
3357
3430
  function classifyWin32Copy(name, p) {
3358
3431
  const sharedPath = join14(repoHome(), "shared", name);
3359
- if (!existsSync10(sharedPath)) return win32CopyUnpublishedRow(name);
3432
+ const sharedState = classifyPresence(sharedPath);
3433
+ if (sharedState === "absent") return win32CopyUnpublishedRow(name);
3434
+ if (isUnusableTarget(sharedState)) return win32CopyUnusableRow(name, sharedState);
3360
3435
  const compared = listDivergingFiles(p, sharedPath);
3361
3436
  const diverging = compared.filter(
3362
3437
  (line) => deniedSegmentFor(divergingRepoPath(line, name, p, sharedPath)) === null
@@ -3370,18 +3445,69 @@ function classifyWin32Copy(name, p) {
3370
3445
  };
3371
3446
  }
3372
3447
 
3448
+ // src/commands.doctor.checks.repo.source.ts
3449
+ init_color();
3450
+ init_config();
3451
+ import { join as join15 } from "node:path";
3452
+ function repoSourceState(name) {
3453
+ return classifyPresence(join15(repoHome(), "shared", name));
3454
+ }
3455
+ function adoptRefusalClause(name, state) {
3456
+ if (state === "dangling") {
3457
+ return `shared/${name} does not resolve, so \`nomad adopt ${name}\` would refuse (remove shared/${name}, or restore what it points at, first)`;
3458
+ }
3459
+ return `shared/${name} could not be read, so \`nomad adopt ${name}\` would refuse (check its permissions in the sync repo first)`;
3460
+ }
3461
+ function adoptWouldClobberRow(name) {
3462
+ return {
3463
+ line: `${red(failGlyph)} ${name}: NOT a symlink (blocks sync), and shared/${name} already holds content, so \`nomad adopt ${name}\` would refuse rather than choose between them (compare the two, then either remove ~/.claude/${name} and run \`nomad pull\`, or remove shared/${name} and run \`nomad adopt ${name}\`)`,
3464
+ fail: true
3465
+ };
3466
+ }
3467
+ function posixNonSymlinkRow(name) {
3468
+ const state = repoSourceState(name);
3469
+ if (isUnusableTarget(state)) {
3470
+ return {
3471
+ line: `${red(failGlyph)} ${name}: NOT a symlink (blocks sync), and ${adoptRefusalClause(name, state)}`,
3472
+ fail: true
3473
+ };
3474
+ }
3475
+ if (state === "resolves") return adoptWouldClobberRow(name);
3476
+ return {
3477
+ line: `${red(failGlyph)} ${name}: NOT a symlink (blocks sync); run \`nomad adopt ${name}\` to fix`,
3478
+ fail: true
3479
+ };
3480
+ }
3481
+ function repoSourceUnusableRow(name, state) {
3482
+ if (state === "dangling") {
3483
+ return {
3484
+ line: `${yellow(warnGlyph)} ${name}: shared/${name} in the repo does not resolve, so there is nothing to restore from (remove shared/${name}, or restore what it points at)`,
3485
+ fail: false
3486
+ };
3487
+ }
3488
+ return {
3489
+ line: `${yellow(warnGlyph)} ${name}: shared/${name} in the repo could not be read, so whether there is anything to restore from could not be determined (check its permissions in the sync repo)`,
3490
+ fail: false
3491
+ };
3492
+ }
3493
+ function repoSourceRow(name, present, absent) {
3494
+ const state = repoSourceState(name);
3495
+ if (isUnusableTarget(state)) return repoSourceUnusableRow(name, state);
3496
+ return state === "resolves" ? present : absent;
3497
+ }
3498
+
3373
3499
  // src/init.classify.ts
3374
3500
  init_config();
3375
3501
  init_utils_json();
3376
- import { existsSync as existsSync11 } from "node:fs";
3377
- import { join as join15 } from "node:path";
3502
+ import { existsSync as existsSync10 } from "node:fs";
3503
+ import { join as join16 } from "node:path";
3378
3504
  function classifyRepoState(repoHome2, host) {
3379
- const basePath = join15(repoHome2, "shared", "settings.base.json");
3380
- const mapPath = join15(repoHome2, "path-map.json");
3381
- const hostPath = join15(repoHome2, "hosts", `${host}.json`);
3382
- const hasBase = existsSync11(basePath);
3383
- const hasMap = existsSync11(mapPath);
3384
- const hasHost = existsSync11(hostPath);
3505
+ const basePath = join16(repoHome2, "shared", "settings.base.json");
3506
+ const mapPath = join16(repoHome2, "path-map.json");
3507
+ const hostPath = join16(repoHome2, "hosts", `${host}.json`);
3508
+ const hasBase = existsSync10(basePath);
3509
+ const hasMap = existsSync10(mapPath);
3510
+ const hasHost = existsSync10(hostPath);
3385
3511
  let mapEntryCount = 0;
3386
3512
  if (hasMap) {
3387
3513
  try {
@@ -3396,11 +3522,11 @@ function classifyRepoState(repoHome2, host) {
3396
3522
  return "partial";
3397
3523
  }
3398
3524
  function reasonForPartial(repoHome2, host) {
3399
- const basePath = join15(repoHome2, "shared", "settings.base.json");
3400
- const mapPath = join15(repoHome2, "path-map.json");
3401
- const hostPath = join15(repoHome2, "hosts", `${host}.json`);
3402
- if (!existsSync11(basePath)) return "- shared/settings.base.json missing";
3403
- if (!existsSync11(mapPath)) return "- path-map.json missing";
3525
+ const basePath = join16(repoHome2, "shared", "settings.base.json");
3526
+ const mapPath = join16(repoHome2, "path-map.json");
3527
+ const hostPath = join16(repoHome2, "hosts", `${host}.json`);
3528
+ if (!existsSync10(basePath)) return "- shared/settings.base.json missing";
3529
+ if (!existsSync10(mapPath)) return "- path-map.json missing";
3404
3530
  let mapEntryCount;
3405
3531
  try {
3406
3532
  const map = readJson(mapPath);
@@ -3409,7 +3535,7 @@ function reasonForPartial(repoHome2, host) {
3409
3535
  mapEntryCount = 0;
3410
3536
  }
3411
3537
  if (mapEntryCount === 0) return "- path-map.json.projects has no entries";
3412
- if (!existsSync11(hostPath)) return `- hosts/${host}.json missing`;
3538
+ if (!existsSync10(hostPath)) return `- hosts/${host}.json missing`;
3413
3539
  return "- partial state (unknown gap)";
3414
3540
  }
3415
3541
 
@@ -3426,15 +3552,15 @@ function reportHostAndPaths(section2) {
3426
3552
  if (isOverrideActive()) {
3427
3553
  addItem(section2, `${dim(infoGlyph)} NOMAD_REPO: ${blue(repo)}`);
3428
3554
  }
3429
- addItem(section2, `${existsSync12(repo) ? green(okGlyph) : yellow(warnGlyph)} repo: ${blue(repo)}`);
3555
+ addItem(section2, `${existsSync11(repo) ? green(okGlyph) : yellow(warnGlyph)} repo: ${blue(repo)}`);
3430
3556
  addItem(
3431
3557
  section2,
3432
- `${existsSync12(claude) ? green(okGlyph) : yellow(warnGlyph)} claude home: ${blue(claude)}`
3558
+ `${existsSync11(claude) ? green(okGlyph) : yellow(warnGlyph)} claude home: ${blue(claude)}`
3433
3559
  );
3434
3560
  }
3435
3561
  function pathMapHostKeys() {
3436
- const mapPath = join16(repoHome(), "path-map.json");
3437
- if (!existsSync12(mapPath)) return /* @__PURE__ */ new Set();
3562
+ const mapPath = join17(repoHome(), "path-map.json");
3563
+ if (!existsSync11(mapPath)) return /* @__PURE__ */ new Set();
3438
3564
  let raw;
3439
3565
  try {
3440
3566
  raw = readJson(mapPath);
@@ -3451,7 +3577,7 @@ function pathMapHostKeys() {
3451
3577
  function hostOverrideLabels() {
3452
3578
  let entries;
3453
3579
  try {
3454
- entries = readdirSync5(join16(repoHome(), "hosts"));
3580
+ entries = readdirSync5(join17(repoHome(), "hosts"));
3455
3581
  } catch {
3456
3582
  return /* @__PURE__ */ new Set();
3457
3583
  }
@@ -3491,9 +3617,6 @@ function reportRepoState(section2) {
3491
3617
  process.exitCode = 1;
3492
3618
  }
3493
3619
  }
3494
- function repoHasSharedSource(name) {
3495
- return existsSync12(join16(repoHome(), "shared", name));
3496
- }
3497
3620
  function classifySharedLink(name, p) {
3498
3621
  let stat;
3499
3622
  try {
@@ -3501,10 +3624,14 @@ function classifySharedLink(name, p) {
3501
3624
  } catch (err) {
3502
3625
  const code = err.code;
3503
3626
  if (code === "ENOENT") {
3504
- return repoHasSharedSource(name) ? {
3505
- line: `${yellow(warnGlyph)} ${name}: missing (run \`nomad pull\` to restore)`,
3506
- fail: false
3507
- } : { line: `${dim(infoGlyph)} ${name}: not synced (nothing in shared/)`, fail: false };
3627
+ return repoSourceRow(
3628
+ name,
3629
+ {
3630
+ line: `${yellow(warnGlyph)} ${name}: missing (run \`nomad pull\` to restore)`,
3631
+ fail: false
3632
+ },
3633
+ { line: `${dim(infoGlyph)} ${name}: not synced (nothing in shared/)`, fail: false }
3634
+ );
3508
3635
  }
3509
3636
  return { line: `${red(failGlyph)} ${name}: could not stat (${String(code)})`, fail: true };
3510
3637
  }
@@ -3512,27 +3639,28 @@ function classifySharedLink(name, p) {
3512
3639
  if (process.platform === "win32") {
3513
3640
  return classifyWin32Copy(name, p);
3514
3641
  }
3515
- return {
3516
- line: `${red(failGlyph)} ${name}: NOT a symlink (blocks sync); run \`nomad adopt ${name}\` to fix`,
3517
- fail: true
3518
- };
3642
+ return posixNonSymlinkRow(name);
3519
3643
  }
3520
3644
  return classifySymlinkTarget(name, p);
3521
3645
  }
3522
3646
  function classifySymlinkTarget(name, p) {
3523
3647
  try {
3524
- statSync3(p);
3648
+ statSync4(p);
3525
3649
  return { line: `${green(okGlyph)} ${name}: symlink`, fail: false };
3526
3650
  } catch (err) {
3527
3651
  const code = err.code;
3528
3652
  if (code === "ENOENT") {
3529
- return repoHasSharedSource(name) ? {
3530
- line: `${yellow(warnGlyph)} ${name}: broken symlink (target missing, run \`nomad pull\`)`,
3531
- fail: false
3532
- } : {
3533
- line: `${dim(infoGlyph)} ${name}: stale symlink (no longer in shared/, safe to remove)`,
3534
- fail: false
3535
- };
3653
+ return repoSourceRow(
3654
+ name,
3655
+ {
3656
+ line: `${yellow(warnGlyph)} ${name}: broken symlink (target missing, run \`nomad pull\`)`,
3657
+ fail: false
3658
+ },
3659
+ {
3660
+ line: `${dim(infoGlyph)} ${name}: stale symlink (no longer in shared/, safe to remove)`,
3661
+ fail: false
3662
+ }
3663
+ );
3536
3664
  }
3537
3665
  return {
3538
3666
  line: `${yellow(warnGlyph)} ${name}: symlink target unreadable (${String(code)})`,
@@ -3543,7 +3671,7 @@ function classifySymlinkTarget(name, p) {
3543
3671
  function reportSharedLinks(section2, map) {
3544
3672
  const claude = claudeHome();
3545
3673
  for (const name of allSharedLinks(map, { quiet: true })) {
3546
- const p = join16(claude, name);
3674
+ const p = join17(claude, name);
3547
3675
  const { line, fail: fail2, children } = classifySharedLink(name, p);
3548
3676
  addItem(section2, line);
3549
3677
  if (fail2) process.exitCode = 1;
@@ -3555,7 +3683,7 @@ function reportSharedLinks(section2, map) {
3555
3683
  function reportDroppedNamesMigration(section2) {
3556
3684
  const claude = claudeHome();
3557
3685
  for (const name of GSD_DROPPED_NAMES) {
3558
- const p = join16(claude, name);
3686
+ const p = join17(claude, name);
3559
3687
  let stat;
3560
3688
  try {
3561
3689
  stat = lstatSync10(p);
@@ -3573,11 +3701,11 @@ function reportDroppedNamesMigration(section2) {
3573
3701
  // src/commands.doctor.checks.settings.ts
3574
3702
  init_color();
3575
3703
  init_config();
3576
- import { existsSync as existsSync13, readdirSync as readdirSync6 } from "node:fs";
3577
- import { join as join17 } from "node:path";
3704
+ import { existsSync as existsSync12, readdirSync as readdirSync6 } from "node:fs";
3705
+ import { join as join18 } from "node:path";
3578
3706
  function loadBaseSettings(section2) {
3579
- const basePath = join17(repoHome(), "shared", "settings.base.json");
3580
- if (!existsSync13(basePath)) {
3707
+ const basePath = join18(repoHome(), "shared", "settings.base.json");
3708
+ if (!existsSync12(basePath)) {
3581
3709
  addItem(section2, `${red(failGlyph)} shared/settings.base.json missing at ${blue(basePath)}`);
3582
3710
  process.exitCode = 1;
3583
3711
  return null;
@@ -3585,8 +3713,8 @@ function loadBaseSettings(section2) {
3585
3713
  return readJsonSafe(basePath, basePath, section2);
3586
3714
  }
3587
3715
  function loadAndReportSettings(section2) {
3588
- const settingsPath = join17(claudeHome(), "settings.json");
3589
- if (!existsSync13(settingsPath)) return null;
3716
+ const settingsPath = join18(claudeHome(), "settings.json");
3717
+ if (!existsSync12(settingsPath)) return null;
3590
3718
  const settings = readJsonSafe(settingsPath, settingsPath, section2);
3591
3719
  if (settings === null) return null;
3592
3720
  const unknownKeys = Object.keys(settings).filter((k) => !KNOWN_SETTINGS_KEYS.has(k));
@@ -3602,13 +3730,13 @@ function loadAndReportSettings(section2) {
3602
3730
  }
3603
3731
  function reportHostOverrides(section2, base, settings) {
3604
3732
  const repo = repoHome();
3605
- const hostFile = join17(repo, "hosts", `${HOST}.json`);
3733
+ const hostFile = join18(repo, "hosts", `${HOST}.json`);
3606
3734
  let drift = [];
3607
3735
  if (base !== null && settings !== null) {
3608
3736
  const baseKeys = new Set(Object.keys(base));
3609
3737
  drift = Object.keys(settings).filter((k) => !baseKeys.has(k));
3610
3738
  }
3611
- if (existsSync13(hostFile)) {
3739
+ if (existsSync12(hostFile)) {
3612
3740
  if (readJsonSafe(hostFile, hostFile, section2) !== null) {
3613
3741
  addItem(section2, `${green(okGlyph)} host overrides: ${blue(hostFile)}`);
3614
3742
  }
@@ -3617,8 +3745,8 @@ function reportHostOverrides(section2, base, settings) {
3617
3745
  section2,
3618
3746
  `${red(failGlyph)} no hosts/${HOST}.json AND settings.json has unbased keys ${JSON.stringify(drift)}`
3619
3747
  );
3620
- const hostsDir = join17(repo, "hosts");
3621
- if (existsSync13(hostsDir)) {
3748
+ const hostsDir = join18(repo, "hosts");
3749
+ if (existsSync12(hostsDir)) {
3622
3750
  const cands = readdirSync6(hostsDir).filter((f) => f.endsWith(".json"));
3623
3751
  if (cands.length > 0) addItem(section2, `${dim(infoGlyph)} candidates: ${cands.join(", ")}`);
3624
3752
  }
@@ -3635,8 +3763,8 @@ function reportHostOverrides(section2, base, settings) {
3635
3763
  init_color();
3636
3764
  init_config();
3637
3765
  init_config_sharedDirs_guard();
3638
- import { existsSync as existsSync14, lstatSync as lstatSync11, readdirSync as readdirSync7, realpathSync as realpathSync2 } from "node:fs";
3639
- import { join as join18, sep as sep4 } from "node:path";
3766
+ import { existsSync as existsSync13, lstatSync as lstatSync11, readdirSync as readdirSync7, realpathSync as realpathSync2 } from "node:fs";
3767
+ import { join as join19, sep as sep4 } from "node:path";
3640
3768
  init_utils_json();
3641
3769
  function reportMappedProjects(section2, map) {
3642
3770
  const mapped = Object.entries(map.projects).filter(([, hosts]) => hosts[HOST]);
@@ -3646,8 +3774,8 @@ function reportMappedProjects(section2, map) {
3646
3774
  }
3647
3775
  }
3648
3776
  function reportUnmappedProjects(section2, map) {
3649
- const localProjects = join18(claudeHome(), "projects");
3650
- if (!existsSync14(localProjects)) return;
3777
+ const localProjects = join19(claudeHome(), "projects");
3778
+ if (!existsSync13(localProjects)) return;
3651
3779
  let localDirs;
3652
3780
  try {
3653
3781
  localDirs = readdirSync7(localProjects);
@@ -3668,7 +3796,7 @@ function reportCurrentHostPathsMissing(section2, map) {
3668
3796
  for (const [name, hosts] of Object.entries(map.projects)) {
3669
3797
  const abspath = hosts[HOST];
3670
3798
  if (!abspath || abspath === "TBD") continue;
3671
- if (!existsSync14(abspath)) {
3799
+ if (!existsSync13(abspath)) {
3672
3800
  addItem(
3673
3801
  section2,
3674
3802
  `${yellow(warnGlyph)} path-map: ${name} local path missing on ${HOST}: ${blue(abspath)}`
@@ -3678,7 +3806,7 @@ function reportCurrentHostPathsMissing(section2, map) {
3678
3806
  }
3679
3807
  function hasSharedLeftover(entry) {
3680
3808
  try {
3681
- return lstatSync11(join18(repoHome(), "shared", entry), { throwIfNoEntry: false }) !== void 0;
3809
+ return lstatSync11(join19(repoHome(), "shared", entry), { throwIfNoEntry: false }) !== void 0;
3682
3810
  } catch {
3683
3811
  return false;
3684
3812
  }
@@ -3688,7 +3816,7 @@ var PROBEABLE_REASONS = /* @__PURE__ */ new Set([
3688
3816
  "secret-shaped"
3689
3817
  ]);
3690
3818
  function classifyLocalLink(entry) {
3691
- const linkPath = join18(claudeHome(), entry);
3819
+ const linkPath = join19(claudeHome(), entry);
3692
3820
  let stat;
3693
3821
  try {
3694
3822
  stat = lstatSync11(linkPath, { throwIfNoEntry: false });
@@ -3704,7 +3832,7 @@ function classifyLocalLink(entry) {
3704
3832
  }
3705
3833
  let root;
3706
3834
  try {
3707
- root = realpathSync2(join18(repoHome(), "shared"));
3835
+ root = realpathSync2(join19(repoHome(), "shared"));
3708
3836
  } catch {
3709
3837
  return "foreign";
3710
3838
  }
@@ -3788,8 +3916,8 @@ function reportPathCollisions(section2, map) {
3788
3916
  else addItem(section2, `${green(okGlyph)} path-encoding: no collisions`);
3789
3917
  }
3790
3918
  function reportPathMap(section2) {
3791
- const mapPath = join18(repoHome(), "path-map.json");
3792
- if (!existsSync14(mapPath)) {
3919
+ const mapPath = join19(repoHome(), "path-map.json");
3920
+ if (!existsSync13(mapPath)) {
3793
3921
  addItem(section2, `${red(failGlyph)} path-map.json missing at ${blue(mapPath)}`);
3794
3922
  process.exitCode = 1;
3795
3923
  return;
@@ -3819,8 +3947,8 @@ function reportNeverSync(section2) {
3819
3947
 
3820
3948
  // src/commands.doctor.checks.skills.ts
3821
3949
  init_color();
3822
- import { existsSync as existsSync15 } from "node:fs";
3823
- import { join as join19 } from "node:path";
3950
+ import { existsSync as existsSync14 } from "node:fs";
3951
+ import { join as join20 } from "node:path";
3824
3952
  init_config();
3825
3953
  function stripSideIndicator(line) {
3826
3954
  if (line.endsWith(" (local only)")) return line.slice(0, -" (local only)".length);
@@ -3840,13 +3968,13 @@ function isGsdDiffLine(line, localBase, sharedBase) {
3840
3968
  return relative12.split("/")[0].startsWith(GSD_PREFIX);
3841
3969
  }
3842
3970
  function reportSkillsDivergence(section2) {
3843
- const sharedSkills = join19(repoHome(), "shared", "skills");
3844
- const localSkills = join19(claudeHome(), "skills");
3845
- if (!existsSync15(sharedSkills)) {
3971
+ const sharedSkills = join20(repoHome(), "shared", "skills");
3972
+ const localSkills = join20(claudeHome(), "skills");
3973
+ if (!existsSync14(sharedSkills)) {
3846
3974
  addItem(section2, `${dim(infoGlyph)} skills: no shared/skills/ to compare`);
3847
3975
  return;
3848
3976
  }
3849
- if (!existsSync15(localSkills)) {
3977
+ if (!existsSync14(localSkills)) {
3850
3978
  addItem(section2, `${dim(infoGlyph)} skills: no local skills/ to compare`);
3851
3979
  return;
3852
3980
  }
@@ -3869,8 +3997,8 @@ function reportSkillsDivergence(section2) {
3869
3997
  init_color();
3870
3998
  init_config();
3871
3999
  import { execFileSync as execFileSync5 } from "node:child_process";
3872
- import { existsSync as existsSync18 } from "node:fs";
3873
- import { join as join23, relative as relative5 } from "node:path";
4000
+ import { existsSync as existsSync17 } from "node:fs";
4001
+ import { join as join24, relative as relative5 } from "node:path";
3874
4002
  init_commands_pull_wedge();
3875
4003
  init_push_checks();
3876
4004
  init_utils();
@@ -3893,8 +4021,8 @@ function reportGitleaksProbe(section2) {
3893
4021
  }
3894
4022
  function reportGitlinks(section2) {
3895
4023
  const repo = repoHome();
3896
- const sharedDir = join23(repo, "shared");
3897
- if (existsSync18(sharedDir)) {
4024
+ const sharedDir = join24(repo, "shared");
4025
+ if (existsSync17(sharedDir)) {
3898
4026
  const gitlinks = findGitlinks(sharedDir);
3899
4027
  for (const p of gitlinks) {
3900
4028
  const rel = relative5(repo, p).replaceAll("\\", "/");
@@ -3992,8 +4120,8 @@ function reportGitIdentity(section2) {
3992
4120
 
3993
4121
  // src/commands.doctor.checks.backups.ts
3994
4122
  init_color();
3995
- import { existsSync as existsSync19, lstatSync as lstatSync12, readdirSync as readdirSync9 } from "node:fs";
3996
- import { join as join24 } from "node:path";
4123
+ import { existsSync as existsSync18, lstatSync as lstatSync12, readdirSync as readdirSync9 } from "node:fs";
4124
+ import { join as join25 } from "node:path";
3997
4125
  init_config();
3998
4126
  var TS_SHAPE2 = /^\d{8}-\d{6}(-\d+)?$/;
3999
4127
  function safeReaddir(dir) {
@@ -4009,7 +4137,7 @@ var BYTES_PER_MB = 1024 * 1024;
4009
4137
  function dirSizeBytes(dir) {
4010
4138
  let bytes = 0;
4011
4139
  for (const entry of safeReaddir(dir)) {
4012
- const full = join24(dir, entry);
4140
+ const full = join25(dir, entry);
4013
4141
  const st = lstatSync12(full, { throwIfNoEntry: false });
4014
4142
  if (!st) continue;
4015
4143
  if (st.isSymbolicLink()) continue;
@@ -4020,11 +4148,11 @@ function dirSizeBytes(dir) {
4020
4148
  }
4021
4149
  function totalSizeMb(backupBase2, dirs) {
4022
4150
  let bytes = 0;
4023
- for (const name of dirs) bytes += dirSizeBytes(join24(backupBase2, name));
4151
+ for (const name of dirs) bytes += dirSizeBytes(join25(backupBase2, name));
4024
4152
  return bytes / BYTES_PER_MB;
4025
4153
  }
4026
4154
  function reportBackupsCheck(section2, backupBase2 = backupBase()) {
4027
- if (!existsSync19(backupBase2)) return;
4155
+ if (!existsSync18(backupBase2)) return;
4028
4156
  const dirs = safeReaddir(backupBase2).filter((n) => TS_SHAPE2.test(n));
4029
4157
  const count = dirs.length;
4030
4158
  const sizeMb = totalSizeMb(backupBase2, dirs);
@@ -4105,8 +4233,8 @@ function reportCheckRemote(section2) {
4105
4233
 
4106
4234
  // src/commands.doctor.check-schema.ts
4107
4235
  init_color();
4108
- import { existsSync as existsSync20 } from "node:fs";
4109
- import { join as join25 } from "node:path";
4236
+ import { existsSync as existsSync19 } from "node:fs";
4237
+ import { join as join26 } from "node:path";
4110
4238
  init_config();
4111
4239
 
4112
4240
  // src/http-fetch.ts
@@ -4143,8 +4271,8 @@ function fetchSchemaKeys() {
4143
4271
  }
4144
4272
  }
4145
4273
  function reportCheckSchema(section2) {
4146
- const settingsPath = join25(claudeHome(), "settings.json");
4147
- if (!existsSync20(settingsPath)) {
4274
+ const settingsPath = join26(claudeHome(), "settings.json");
4275
+ if (!existsSync19(settingsPath)) {
4148
4276
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json to check`);
4149
4277
  return;
4150
4278
  }
@@ -4174,9 +4302,9 @@ function reportCheckSchema(section2) {
4174
4302
  init_color();
4175
4303
  import { randomBytes as randomBytes3 } from "node:crypto";
4176
4304
  import { execFileSync as execFileSync11 } from "node:child_process";
4177
- import { existsSync as existsSync23, mkdirSync as mkdirSync8, readdirSync as readdirSync12, rmSync as rmSync12 } from "node:fs";
4305
+ import { existsSync as existsSync22, mkdirSync as mkdirSync8, readdirSync as readdirSync12, rmSync as rmSync12 } from "node:fs";
4178
4306
  import { homedir as homedir6 } from "node:os";
4179
- import { join as join32 } from "node:path";
4307
+ import { join as join33 } from "node:path";
4180
4308
 
4181
4309
  // src/commands.doctor.check-shared.memory.ts
4182
4310
  init_color();
@@ -4184,7 +4312,7 @@ import { execFileSync as execFileSync9 } from "node:child_process";
4184
4312
  import { randomBytes } from "node:crypto";
4185
4313
  import { mkdirSync as mkdirSync4, rmSync as rmSync9, writeFileSync as writeFileSync4 } from "node:fs";
4186
4314
  import { homedir as homedir4 } from "node:os";
4187
- import { dirname as dirname4, join as join27 } from "node:path";
4315
+ import { dirname as dirname4, join as join28 } from "node:path";
4188
4316
  init_config();
4189
4317
  init_push_gitleaks();
4190
4318
  init_utils_fs();
@@ -4217,7 +4345,7 @@ function buildMemoryScanTree(tmpRoot) {
4217
4345
  incomplete = true;
4218
4346
  continue;
4219
4347
  }
4220
- const dest = join27(tmpRoot, rel);
4348
+ const dest = join28(tmpRoot, rel);
4221
4349
  mkdirSync4(dirname4(dest), { recursive: true });
4222
4350
  writeFileSync4(dest, blob);
4223
4351
  logicals.add(m[1]);
@@ -4236,10 +4364,10 @@ function reportMemoryFindings(section2, findings) {
4236
4364
  function reportCommittedMemory(section2) {
4237
4365
  let tmpRoot;
4238
4366
  try {
4239
- const cacheDir = join27(homedir4(), ".cache", "claude-nomad");
4367
+ const cacheDir = join28(homedir4(), ".cache", "claude-nomad");
4240
4368
  mkdirSync4(cacheDir, { recursive: true });
4241
4369
  const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes(4).toString("hex")}`;
4242
- tmpRoot = join27(cacheDir, `check-shared-memory-tree-${stamp}`);
4370
+ tmpRoot = join28(cacheDir, `check-shared-memory-tree-${stamp}`);
4243
4371
  mkdirSync4(tmpRoot, { recursive: true, mode: 448 });
4244
4372
  const { staged, incomplete } = buildMemoryScanTree(tmpRoot);
4245
4373
  if (incomplete) {
@@ -4286,12 +4414,12 @@ function reportCommittedMemory(section2) {
4286
4414
 
4287
4415
  // src/commands.doctor.check-shared.scan.ts
4288
4416
  init_color();
4289
- import { join as join28 } from "node:path";
4417
+ import { join as join29 } from "node:path";
4290
4418
  init_config();
4291
4419
  init_push_gitleaks();
4292
4420
  function scrubPath(logical, sid, logicalToEncoded) {
4293
4421
  const encoded = logicalToEncoded.get(logical) ?? logical;
4294
- return join28(claudeHome(), "projects", encoded, `${sid}.jsonl`);
4422
+ return join29(claudeHome(), "projects", encoded, `${sid}.jsonl`);
4295
4423
  }
4296
4424
  function reportSessionFindings(section2, bySession) {
4297
4425
  for (const [sid, counts] of bySession) {
@@ -4380,7 +4508,7 @@ import { execFileSync as execFileSync10 } from "node:child_process";
4380
4508
  import { randomBytes as randomBytes2 } from "node:crypto";
4381
4509
  import { mkdirSync as mkdirSync5, rmSync as rmSync10, writeFileSync as writeFileSync5 } from "node:fs";
4382
4510
  import { homedir as homedir5 } from "node:os";
4383
- import { dirname as dirname5, join as join29 } from "node:path";
4511
+ import { dirname as dirname5, join as join30 } from "node:path";
4384
4512
  init_config();
4385
4513
  init_push_gitleaks();
4386
4514
  init_utils_fs();
@@ -4413,7 +4541,7 @@ function buildSkillScanTree(tmpRoot) {
4413
4541
  incomplete = true;
4414
4542
  continue;
4415
4543
  }
4416
- const dest = join29(tmpRoot, rel);
4544
+ const dest = join30(tmpRoot, rel);
4417
4545
  mkdirSync5(dirname5(dest), { recursive: true });
4418
4546
  writeFileSync5(dest, blob);
4419
4547
  names.add(m[1]);
@@ -4436,10 +4564,10 @@ function reportSkillFindings(section2, findings) {
4436
4564
  function reportCommittedSkills(section2) {
4437
4565
  let tmpRoot;
4438
4566
  try {
4439
- const cacheDir = join29(homedir5(), ".cache", "claude-nomad");
4567
+ const cacheDir = join30(homedir5(), ".cache", "claude-nomad");
4440
4568
  mkdirSync5(cacheDir, { recursive: true });
4441
4569
  const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes2(4).toString("hex")}`;
4442
- tmpRoot = join29(cacheDir, `check-shared-skills-tree-${stamp}`);
4570
+ tmpRoot = join30(cacheDir, `check-shared-skills-tree-${stamp}`);
4443
4571
  mkdirSync5(tmpRoot, { recursive: true, mode: 448 });
4444
4572
  const { staged, incomplete } = buildSkillScanTree(tmpRoot);
4445
4573
  if (incomplete) {
@@ -4489,8 +4617,8 @@ init_config();
4489
4617
 
4490
4618
  // src/remap.ts
4491
4619
  init_config_sharedDirs_guard();
4492
- import { cpSync as cpSync5, existsSync as existsSync22, lstatSync as lstatSync13, mkdirSync as mkdirSync7, readdirSync as readdirSync11, rmSync as rmSync11, statSync as statSync5 } from "node:fs";
4493
- import { dirname as dirname7, join as join31, relative as relative6, sep as sep5 } from "node:path";
4620
+ import { cpSync as cpSync5, existsSync as existsSync21, lstatSync as lstatSync13, mkdirSync as mkdirSync7, readdirSync as readdirSync11, rmSync as rmSync11, statSync as statSync6 } from "node:fs";
4621
+ import { dirname as dirname7, join as join32, relative as relative6, sep as sep5 } from "node:path";
4494
4622
  init_config();
4495
4623
 
4496
4624
  // src/push-manifest.ts
@@ -4498,8 +4626,8 @@ init_config();
4498
4626
  init_push_gitleaks_config();
4499
4627
  init_utils_fs();
4500
4628
  import { createHash } from "node:crypto";
4501
- import { existsSync as existsSync21, mkdirSync as mkdirSync6, readdirSync as readdirSync10, readFileSync as readFileSync7, statSync as statSync4 } from "node:fs";
4502
- import { dirname as dirname6, join as join30 } from "node:path";
4629
+ import { existsSync as existsSync20, mkdirSync as mkdirSync6, readdirSync as readdirSync10, readFileSync as readFileSync7, statSync as statSync5 } from "node:fs";
4630
+ import { dirname as dirname6, join as join31 } from "node:path";
4503
4631
  function isChanged(prev, cur, hash) {
4504
4632
  if (prev === void 0) return true;
4505
4633
  if (prev.size !== cur.size) return true;
@@ -4540,8 +4668,8 @@ function hashFile(absPath) {
4540
4668
  }
4541
4669
  function enumerateDir(dir, results) {
4542
4670
  for (const entry of readdirSync10(dir)) {
4543
- const fullPath = join30(dir, entry);
4544
- const st = statSync4(fullPath);
4671
+ const fullPath = join31(dir, entry);
4672
+ const st = statSync5(fullPath);
4545
4673
  if (st.isDirectory()) {
4546
4674
  enumerateDir(fullPath, results);
4547
4675
  } else {
@@ -4552,8 +4680,8 @@ function enumerateDir(dir, results) {
4552
4680
  function enumerateSourceFiles(projectDir) {
4553
4681
  const results = [];
4554
4682
  for (const entry of readdirSync10(projectDir)) {
4555
- const fullPath = join30(projectDir, entry);
4556
- const st = statSync4(fullPath);
4683
+ const fullPath = join31(projectDir, entry);
4684
+ const st = statSync5(fullPath);
4557
4685
  if (st.isDirectory()) {
4558
4686
  enumerateDir(fullPath, results);
4559
4687
  } else if (fullPath.endsWith(".jsonl")) {
@@ -4564,15 +4692,15 @@ function enumerateSourceFiles(projectDir) {
4564
4692
  }
4565
4693
  function fileIdentity(p) {
4566
4694
  if (p === null) return "none::absent";
4567
- if (!existsSync21(p)) return `${p}::absent`;
4695
+ if (!existsSync20(p)) return `${p}::absent`;
4568
4696
  return `${p}::${createHash("sha256").update(readFileSync7(p)).digest("hex")}`;
4569
4697
  }
4570
4698
  function computeConfigHash() {
4571
4699
  const repo = repoHome();
4572
4700
  const parts = [
4573
4701
  fileIdentity(resolveTomlPath(repo)),
4574
- fileIdentity(join30(repo, ".gitleaks.overlay.toml")),
4575
- fileIdentity(join30(repo, ".gitleaksignore"))
4702
+ fileIdentity(join31(repo, ".gitleaks.overlay.toml")),
4703
+ fileIdentity(join31(repo, ".gitleaksignore"))
4576
4704
  ];
4577
4705
  return createHash("sha256").update(parts.join("\n")).digest("hex");
4578
4706
  }
@@ -4634,12 +4762,12 @@ function applySelective(sel, localDir, repoDst) {
4634
4762
  const prefix = `${localDir}${sep5}`;
4635
4763
  for (const src of sel.changed) {
4636
4764
  if (!src.startsWith(prefix)) continue;
4637
- copyFileAtomic(src, join31(repoDst, relative6(localDir, src)));
4765
+ copyFileAtomic(src, join32(repoDst, relative6(localDir, src)));
4638
4766
  }
4639
4767
  for (const src of sel.deleted) {
4640
4768
  if (!src.startsWith(prefix)) continue;
4641
- const dst = join31(repoDst, relative6(localDir, src));
4642
- if (existsSync22(dst)) rmSync11(dst);
4769
+ const dst = join32(repoDst, relative6(localDir, src));
4770
+ if (existsSync21(dst)) rmSync11(dst);
4643
4771
  }
4644
4772
  }
4645
4773
  function copyDirJsonlOnly(src, dst) {
@@ -4650,7 +4778,7 @@ function copyDirJsonlOnly(src, dst) {
4650
4778
  const rel = relative6(src, srcPath);
4651
4779
  if (rel === "") return true;
4652
4780
  if (rel.split(sep5).length > 1) return true;
4653
- if (statSync5(srcPath).isDirectory()) return true;
4781
+ if (statSync6(srcPath).isDirectory()) return true;
4654
4782
  if (srcPath.endsWith(".jsonl")) return true;
4655
4783
  item(`skip ${rel}: extension not in allowlist`);
4656
4784
  return false;
@@ -4668,15 +4796,15 @@ function remapPull(ts, opts = {}) {
4668
4796
  const wouldPull = [];
4669
4797
  const repo = repoHome();
4670
4798
  const claude = claudeHome();
4671
- const mapPath = join31(repo, "path-map.json");
4672
- const repoProjects = join31(repo, "shared", "projects");
4673
- if (!existsSync22(mapPath) || !existsSync22(repoProjects)) {
4799
+ const mapPath = join32(repo, "path-map.json");
4800
+ const repoProjects = join32(repo, "shared", "projects");
4801
+ if (!existsSync21(mapPath) || !existsSync21(repoProjects)) {
4674
4802
  const text = "no path-map or repo projects dir; skipping session remap";
4675
4803
  emitPreview(opts.onPreview, { kind: "note", text }, text);
4676
4804
  return { unmapped: 0, pulled, wouldPull };
4677
4805
  }
4678
4806
  const map = readPathMap(mapPath);
4679
- const localProjects = join31(claude, "projects");
4807
+ const localProjects = join32(claude, "projects");
4680
4808
  if (!dryRun) mkdirSync7(localProjects, { recursive: true });
4681
4809
  for (const [logical, hosts] of Object.entries(map.projects)) {
4682
4810
  assertSafeLogical(logical);
@@ -4686,9 +4814,9 @@ function remapPull(ts, opts = {}) {
4686
4814
  continue;
4687
4815
  }
4688
4816
  assertSafeLocalRoot(localPath, logical);
4689
- const src = join31(repoProjects, logical);
4690
- if (!existsSync22(src)) continue;
4691
- const dst = join31(localProjects, encodePath(localPath));
4817
+ const src = join32(repoProjects, logical);
4818
+ if (!existsSync21(src)) continue;
4819
+ const dst = join32(localProjects, encodePath(localPath));
4692
4820
  if (dryRun) {
4693
4821
  wouldPull.push(logical);
4694
4822
  emitPreview(
@@ -4707,8 +4835,8 @@ function remapPull(ts, opts = {}) {
4707
4835
  function countLocalOnly(src, dst) {
4708
4836
  let count = 0;
4709
4837
  for (const name of readdirSync11(dst)) {
4710
- const dstPath = join31(dst, name);
4711
- const srcPath = join31(src, name);
4838
+ const dstPath = join32(dst, name);
4839
+ const srcPath = join32(src, name);
4712
4840
  if (lstatSync13(dstPath).isDirectory()) {
4713
4841
  count += countLocalOnly(srcPath, dstPath);
4714
4842
  } else if (lstatSync13(srcPath, { throwIfNoEntry: false }) === void 0) {
@@ -4720,20 +4848,20 @@ function countLocalOnly(src, dst) {
4720
4848
  function scanLocalOnly() {
4721
4849
  const repo = repoHome();
4722
4850
  const claude = claudeHome();
4723
- const mapPath = join31(repo, "path-map.json");
4724
- const repoProjects = join31(repo, "shared", "projects");
4725
- if (!existsSync22(mapPath) || !existsSync22(repoProjects)) return 0;
4851
+ const mapPath = join32(repo, "path-map.json");
4852
+ const repoProjects = join32(repo, "shared", "projects");
4853
+ if (!existsSync21(mapPath) || !existsSync21(repoProjects)) return 0;
4726
4854
  const map = readPathMap(mapPath);
4727
- const localProjects = join31(claude, "projects");
4855
+ const localProjects = join32(claude, "projects");
4728
4856
  let count = 0;
4729
4857
  for (const [logical, hosts] of Object.entries(map.projects)) {
4730
4858
  assertSafeLogical(logical);
4731
4859
  const localPath = hosts[HOST];
4732
4860
  if (!localPath || localPath === "TBD") continue;
4733
4861
  assertSafeLocalRoot(localPath, logical);
4734
- const dst = join31(localProjects, encodePath(localPath));
4735
- if (!existsSync22(dst)) continue;
4736
- count += countLocalOnly(join31(repoProjects, logical), dst);
4862
+ const dst = join32(localProjects, encodePath(localPath));
4863
+ if (!existsSync21(dst)) continue;
4864
+ count += countLocalOnly(join32(repoProjects, logical), dst);
4737
4865
  }
4738
4866
  return count;
4739
4867
  }
@@ -4768,16 +4896,16 @@ function remapPush(ts, opts = {}) {
4768
4896
  const wouldPush = [];
4769
4897
  const repo = repoHome();
4770
4898
  const claude = claudeHome();
4771
- const mapPath = join31(repo, "path-map.json");
4772
- if (!existsSync22(mapPath)) {
4899
+ const mapPath = join32(repo, "path-map.json");
4900
+ if (!existsSync21(mapPath)) {
4773
4901
  log("no path-map.json; skipping session export");
4774
4902
  return { unmapped: 0, collisions: 0, pushed, wouldPush };
4775
4903
  }
4776
4904
  const map = readPathMap(mapPath);
4777
- const localProjects = join31(claude, "projects");
4778
- const repoProjects = join31(repo, "shared", "projects");
4905
+ const localProjects = join32(claude, "projects");
4906
+ const repoProjects = join32(repo, "shared", "projects");
4779
4907
  const reverse = buildReverseMap(map);
4780
- if (!existsSync22(localProjects)) return { unmapped, collisions: 0, pushed, wouldPush };
4908
+ if (!existsSync21(localProjects)) return { unmapped, collisions: 0, pushed, wouldPush };
4781
4909
  if (!dryRun) mkdirSync7(repoProjects, { recursive: true });
4782
4910
  for (const dir of readdirSync11(localProjects)) {
4783
4911
  if (dir.endsWith(TMP_SUFFIX)) continue;
@@ -4786,8 +4914,8 @@ function remapPush(ts, opts = {}) {
4786
4914
  unmapped++;
4787
4915
  continue;
4788
4916
  }
4789
- const localDir = join31(localProjects, dir);
4790
- const repoDst = join31(repoProjects, logical);
4917
+ const localDir = join32(localProjects, dir);
4918
+ const repoDst = join32(repoProjects, logical);
4791
4919
  if (skipForSelection(opts.selection, localDir)) continue;
4792
4920
  if (dryRun) {
4793
4921
  wouldPush.push(logical);
@@ -4811,8 +4939,8 @@ function buildScanTree(tmpRoot) {
4811
4939
  const logicalToEncoded = /* @__PURE__ */ new Map();
4812
4940
  let staged = 0;
4813
4941
  const repo = repoHome();
4814
- const mapPath = join32(repo, "path-map.json");
4815
- if (!existsSync23(mapPath)) return { logicalToEncoded, staged, malformed: false };
4942
+ const mapPath = join33(repo, "path-map.json");
4943
+ if (!existsSync22(mapPath)) return { logicalToEncoded, staged, malformed: false };
4816
4944
  let map;
4817
4945
  try {
4818
4946
  map = readJson(mapPath);
@@ -4829,12 +4957,12 @@ function buildScanTree(tmpRoot) {
4829
4957
  if (!p || p === "TBD") continue;
4830
4958
  reverse.set(encodePath(p), logical);
4831
4959
  }
4832
- const localProjects = join32(claudeHome(), "projects");
4833
- if (!existsSync23(localProjects)) return { logicalToEncoded, staged, malformed: false };
4960
+ const localProjects = join33(claudeHome(), "projects");
4961
+ if (!existsSync22(localProjects)) return { logicalToEncoded, staged, malformed: false };
4834
4962
  for (const dir of readdirSync12(localProjects)) {
4835
4963
  const logical = reverse.get(dir);
4836
4964
  if (!logical) continue;
4837
- copyDirJsonlOnly(join32(localProjects, dir), join32(tmpRoot, "shared", "projects", logical));
4965
+ copyDirJsonlOnly(join33(localProjects, dir), join33(tmpRoot, "shared", "projects", logical));
4838
4966
  logicalToEncoded.set(logical, dir);
4839
4967
  staged++;
4840
4968
  }
@@ -4864,11 +4992,11 @@ function ensureGitleaksReady(section2, gitleaksReady) {
4864
4992
  return true;
4865
4993
  }
4866
4994
  function runLocalPreviewScan(section2) {
4867
- const cacheDir = join32(homedir6(), ".cache", "claude-nomad");
4995
+ const cacheDir = join33(homedir6(), ".cache", "claude-nomad");
4868
4996
  mkdirSync8(cacheDir, { recursive: true });
4869
4997
  const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes3(4).toString("hex")}`;
4870
- const reportPath = join32(cacheDir, `check-shared-${stamp}.json`);
4871
- const tmpRoot = join32(cacheDir, `check-shared-tree-${stamp}`);
4998
+ const reportPath = join33(cacheDir, `check-shared-${stamp}.json`);
4999
+ const tmpRoot = join33(cacheDir, `check-shared-tree-${stamp}`);
4872
5000
  try {
4873
5001
  const { logicalToEncoded, staged, malformed } = buildScanTree(tmpRoot);
4874
5002
  if (malformed) {
@@ -4901,8 +5029,8 @@ function reportCheckShared(section2, gitleaksReady) {
4901
5029
 
4902
5030
  // src/commands.doctor.checks.hooks.scope.ts
4903
5031
  init_color();
4904
- import { existsSync as existsSync24, readFileSync as readFileSync8, readdirSync as readdirSync13, realpathSync as realpathSync3 } from "node:fs";
4905
- import { dirname as dirname8, extname, join as join33 } from "node:path";
5032
+ import { existsSync as existsSync23, readFileSync as readFileSync8, readdirSync as readdirSync13, realpathSync as realpathSync3 } from "node:fs";
5033
+ import { dirname as dirname8, extname, join as join34 } from "node:path";
4906
5034
  init_config();
4907
5035
  function typeFromPackageJson(pkgPath) {
4908
5036
  try {
@@ -4924,8 +5052,8 @@ function effectiveType(hookPath) {
4924
5052
  }
4925
5053
  let dir = dirname8(real);
4926
5054
  for (; ; ) {
4927
- const pkg = join33(dir, "package.json");
4928
- if (existsSync24(pkg)) return typeFromPackageJson(pkg);
5055
+ const pkg = join34(dir, "package.json");
5056
+ if (existsSync23(pkg)) return typeFromPackageJson(pkg);
4929
5057
  const parent = dirname8(dir);
4930
5058
  if (parent === dir) return "cjs";
4931
5059
  dir = parent;
@@ -4967,15 +5095,15 @@ function safeRead(path) {
4967
5095
  }
4968
5096
  }
4969
5097
  function reportHookScopeCheck(section2) {
4970
- const hooksDir = join33(claudeHome(), "hooks");
4971
- if (!existsSync24(hooksDir)) {
5098
+ const hooksDir = join34(claudeHome(), "hooks");
5099
+ if (!existsSync23(hooksDir)) {
4972
5100
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/hooks; skipping module-scope check`);
4973
5101
  return;
4974
5102
  }
4975
5103
  let anyWarn = false;
4976
5104
  for (const name of safeReaddir2(hooksDir)) {
4977
5105
  if (extname(name) !== ".js") continue;
4978
- const abs = join33(hooksDir, name);
5106
+ const abs = join34(hooksDir, name);
4979
5107
  const eff = effectiveType(abs);
4980
5108
  if (eff === null) continue;
4981
5109
  const src = safeRead(abs);
@@ -4995,8 +5123,8 @@ function reportHookScopeCheck(section2) {
4995
5123
 
4996
5124
  // src/commands.doctor.checks.hooks.ts
4997
5125
  init_color();
4998
- import { existsSync as existsSync25 } from "node:fs";
4999
- import { join as join34 } from "node:path";
5126
+ import { existsSync as existsSync24 } from "node:fs";
5127
+ import { join as join35 } from "node:path";
5000
5128
  init_config();
5001
5129
  function expandHome(token) {
5002
5130
  const h2 = home();
@@ -5039,7 +5167,7 @@ function checkEventGroups(section2, event, groups) {
5039
5167
  for (const group of groups) {
5040
5168
  for (const cmd of commandsFromGroup(group)) {
5041
5169
  for (const resolved of claudePathsIn(cmd)) {
5042
- if (existsSync25(resolved)) continue;
5170
+ if (existsSync24(resolved)) continue;
5043
5171
  addItem(
5044
5172
  section2,
5045
5173
  `${red(failGlyph)} hooks/${event}: command target missing: ${resolved} (run nomad pull)`
@@ -5052,8 +5180,8 @@ function checkEventGroups(section2, event, groups) {
5052
5180
  return anyFail;
5053
5181
  }
5054
5182
  function reportHooksTargetCheck(section2) {
5055
- const settingsPath = join34(claudeHome(), "settings.json");
5056
- if (!existsSync25(settingsPath)) {
5183
+ const settingsPath = join35(claudeHome(), "settings.json");
5184
+ if (!existsSync24(settingsPath)) {
5057
5185
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json; skipping hook target check`);
5058
5186
  return;
5059
5187
  }
@@ -5076,12 +5204,12 @@ function reportHooksTargetCheck(section2) {
5076
5204
 
5077
5205
  // src/commands.doctor.checks.hooks.preserve-symlinks.ts
5078
5206
  init_color();
5079
- import { existsSync as existsSync27, readFileSync as readFileSync9 } from "node:fs";
5080
- import { join as join36 } from "node:path";
5207
+ import { existsSync as existsSync26, readFileSync as readFileSync9 } from "node:fs";
5208
+ import { join as join37 } from "node:path";
5081
5209
 
5082
5210
  // src/commands.doctor.checks.hooks.preserve-symlinks.probe.ts
5083
- import { closeSync as closeSync3, existsSync as existsSync26, openSync as openSync3, readSync, realpathSync as realpathSync4 } from "node:fs";
5084
- import { dirname as dirname9, join as join35, resolve as resolve3 } from "node:path";
5211
+ import { closeSync as closeSync3, existsSync as existsSync25, openSync as openSync3, readSync, realpathSync as realpathSync4 } from "node:fs";
5212
+ import { dirname as dirname9, join as join36, resolve as resolve3 } from "node:path";
5085
5213
  function suppressedRanges(src) {
5086
5214
  const ranges = [];
5087
5215
  const re = /\/\*[\s\S]*?\*\/|\/\/[^\n]*|'[^']*'|"[^"]*"|`[^`]*`/g;
@@ -5113,12 +5241,12 @@ function topRelativeSpecifiers(src) {
5113
5241
  }
5114
5242
  function specifierIsMissing(specifier, baseDir) {
5115
5243
  const base = resolve3(baseDir, specifier);
5116
- if (existsSync26(base)) return false;
5244
+ if (existsSync25(base)) return false;
5117
5245
  for (const ext of [".js", ".cjs", ".mjs"]) {
5118
- if (existsSync26(base + ext)) return false;
5246
+ if (existsSync25(base + ext)) return false;
5119
5247
  }
5120
5248
  for (const idx of ["index.js", "index.cjs", "index.mjs"]) {
5121
- if (existsSync26(join35(base, idx))) return false;
5249
+ if (existsSync25(join36(base, idx))) return false;
5122
5250
  }
5123
5251
  return true;
5124
5252
  }
@@ -5173,8 +5301,8 @@ function commandTokens(command) {
5173
5301
  return tokens;
5174
5302
  }
5175
5303
  function readPathMapSafe() {
5176
- const mapPath = join36(repoHome(), "path-map.json");
5177
- if (!existsSync27(mapPath)) return { projects: {} };
5304
+ const mapPath = join37(repoHome(), "path-map.json");
5305
+ if (!existsSync26(mapPath)) return { projects: {} };
5178
5306
  try {
5179
5307
  return JSON.parse(readFileSync9(mapPath, "utf8"));
5180
5308
  } catch {
@@ -5248,8 +5376,8 @@ function checkEventForPreserveSymlinks(section2, event, groups, sharedLinkNames)
5248
5376
  return anyWarn;
5249
5377
  }
5250
5378
  function reportPreserveSymlinksCheck(section2) {
5251
- const settingsPath = join36(claudeHome(), "settings.json");
5252
- if (!existsSync27(settingsPath)) {
5379
+ const settingsPath = join37(claudeHome(), "settings.json");
5380
+ if (!existsSync26(settingsPath)) {
5253
5381
  addItem(
5254
5382
  section2,
5255
5383
  `${dim(infoGlyph)} no ~/.claude/settings.json; skipping preserve-symlinks-main check`
@@ -5282,8 +5410,8 @@ function reportPreserveSymlinksCheck(section2) {
5282
5410
 
5283
5411
  // src/commands.doctor.checks.settings-drift.ts
5284
5412
  init_color();
5285
- import { existsSync as existsSync28, readFileSync as readFileSync10 } from "node:fs";
5286
- import { join as join37 } from "node:path";
5413
+ import { existsSync as existsSync27, readFileSync as readFileSync10 } from "node:fs";
5414
+ import { join as join38 } from "node:path";
5287
5415
  init_config();
5288
5416
  init_utils_json();
5289
5417
  function diffMergedSettings(merged, settings) {
@@ -5301,7 +5429,7 @@ function tryReadJson(filePath) {
5301
5429
  }
5302
5430
  }
5303
5431
  function reportHooksBaseSelfCleanNote(section2) {
5304
- const basePath = join37(repoHome(), "shared", "settings.base.json");
5432
+ const basePath = join38(repoHome(), "shared", "settings.base.json");
5305
5433
  const base = tryReadJson(basePath);
5306
5434
  if (base === null) return;
5307
5435
  if (!baseHasGsdHookEntries(base)) return;
@@ -5314,14 +5442,14 @@ function reportSettingsDriftCheck(section2) {
5314
5442
  const claude = claudeHome();
5315
5443
  const repo = repoHome();
5316
5444
  const host = HOST;
5317
- const settingsPath = join37(claude, "settings.json");
5318
- const basePath = join37(repo, "shared", "settings.base.json");
5319
- const hostPath = join37(repo, "hosts", `${host}.json`);
5320
- if (!existsSync28(settingsPath)) {
5445
+ const settingsPath = join38(claude, "settings.json");
5446
+ const basePath = join38(repo, "shared", "settings.base.json");
5447
+ const hostPath = join38(repo, "hosts", `${host}.json`);
5448
+ if (!existsSync27(settingsPath)) {
5321
5449
  addItem(section2, `${dim(infoGlyph)} no ~/.claude/settings.json; skipping merge-drift check`);
5322
5450
  return;
5323
5451
  }
5324
- if (!existsSync28(basePath)) {
5452
+ if (!existsSync27(basePath)) {
5325
5453
  addItem(
5326
5454
  section2,
5327
5455
  `${dim(infoGlyph)} shared/settings.base.json missing; skipping merge-drift check`
@@ -5340,7 +5468,7 @@ function reportSettingsDriftCheck(section2) {
5340
5468
  if (settings === null) {
5341
5469
  return;
5342
5470
  }
5343
- const hostExists = existsSync28(hostPath);
5471
+ const hostExists = existsSync27(hostPath);
5344
5472
  const hostObj = hostExists ? tryReadJson(hostPath) : null;
5345
5473
  if (hostExists && hostObj === null) {
5346
5474
  addItem(
@@ -5557,15 +5685,15 @@ function reportSyncModality(section2) {
5557
5685
  // src/commands.doctor.checks.crlf.ts
5558
5686
  init_color();
5559
5687
  import { execFileSync as execFileSync13 } from "node:child_process";
5560
- import { existsSync as existsSync29, readFileSync as readFileSync13 } from "node:fs";
5561
- import { join as join38 } from "node:path";
5688
+ import { existsSync as existsSync28, readFileSync as readFileSync13 } from "node:fs";
5689
+ import { join as join39 } from "node:path";
5562
5690
  init_config();
5563
5691
  var PROBE_TIMEOUT_MS2 = 3e3;
5564
5692
  var GUARD_LINE = /^\*\s+-text\b/;
5565
5693
  function hasGitattributesGuard(repo) {
5566
5694
  try {
5567
- const path = join38(repo, ".gitattributes");
5568
- if (!existsSync29(path)) return false;
5695
+ const path = join39(repo, ".gitattributes");
5696
+ if (!existsSync28(path)) return false;
5569
5697
  const content = readFileSync13(path, "utf8");
5570
5698
  return content.split("\n").map((line) => line.trim()).some((line) => line !== "" && !line.startsWith("#") && GUARD_LINE.test(line));
5571
5699
  } catch {
@@ -5606,14 +5734,14 @@ function reportCrlfGuardCheck(section2, run = execFileSync13) {
5606
5734
 
5607
5735
  // src/spinner.ts
5608
5736
  init_color();
5609
- import { existsSync as existsSync34 } from "node:fs";
5737
+ import { existsSync as existsSync33 } from "node:fs";
5610
5738
  import { fileURLToPath as fileURLToPath4 } from "node:url";
5611
5739
  import { Worker } from "node:worker_threads";
5612
5740
 
5613
5741
  // src/commands.push.recovery.ts
5614
5742
  init_config();
5615
5743
  import { readFileSync as readFileSync18, rmSync as rmSync15, writeFileSync as writeFileSync9 } from "node:fs";
5616
- import { join as join46 } from "node:path";
5744
+ import { join as join47 } from "node:path";
5617
5745
  import { createInterface as createInterface2 } from "node:readline/promises";
5618
5746
 
5619
5747
  // src/commands.push.recovery.actions.ts
@@ -5630,10 +5758,10 @@ import {
5630
5758
  mkdirSync as mkdirSync9,
5631
5759
  readFileSync as readFileSync14,
5632
5760
  realpathSync as realpathSync5,
5633
- statSync as statSync6,
5761
+ statSync as statSync7,
5634
5762
  writeFileSync as writeFileSync6
5635
5763
  } from "node:fs";
5636
- import { dirname as dirname10, join as join39, sep as sep6 } from "node:path";
5764
+ import { dirname as dirname10, join as join40, sep as sep6 } from "node:path";
5637
5765
  init_push_gitleaks_scan();
5638
5766
 
5639
5767
  // src/rel-path-guard.ts
@@ -5662,15 +5790,15 @@ function resolveMemoryLocalPath(logical, relPath, map) {
5662
5790
  if (!isSafeRelPath(relPath)) return null;
5663
5791
  const abs = map.projects[logical]?.[HOST];
5664
5792
  if (abs === void 0) return null;
5665
- const memoryRoot = join39(claudeHome(), "projects", encodePath(abs), "memory");
5666
- const localPath = join39(memoryRoot, ...relPath.split("/"));
5793
+ const memoryRoot = join40(claudeHome(), "projects", encodePath(abs), "memory");
5794
+ const localPath = join40(memoryRoot, ...relPath.split("/"));
5667
5795
  if (localPath !== memoryRoot && !localPath.startsWith(memoryRoot + sep6)) return null;
5668
5796
  try {
5669
5797
  if (lstatSync14(localPath).isSymbolicLink()) return null;
5670
5798
  const realLocal = realpathSync5(localPath);
5671
5799
  const realRoot = realpathSync5(memoryRoot);
5672
5800
  if (!realLocal.startsWith(realRoot + sep6)) return null;
5673
- if (!statSync6(realLocal).isFile()) return null;
5801
+ if (!statSync7(realLocal).isFile()) return null;
5674
5802
  } catch {
5675
5803
  return null;
5676
5804
  }
@@ -5717,7 +5845,7 @@ function applyMemoryRedact(f, ts, map, scan = scanFile) {
5717
5845
  );
5718
5846
  }
5719
5847
  writeFileSync6(localPath, after, "utf8");
5720
- const dest = join39(repoHome(), "shared", "projects", logical, "memory", ...relPath.split("/"));
5848
+ const dest = join40(repoHome(), "shared", "projects", logical, "memory", ...relPath.split("/"));
5721
5849
  mkdirSync9(dirname10(dest), { recursive: true });
5722
5850
  cpSync6(localPath, dest, { force: true });
5723
5851
  return true;
@@ -5731,15 +5859,15 @@ import {
5731
5859
  mkdirSync as mkdirSync11,
5732
5860
  readFileSync as readFileSync15,
5733
5861
  realpathSync as realpathSync6,
5734
- statSync as statSync7,
5862
+ statSync as statSync8,
5735
5863
  writeFileSync as writeFileSync7
5736
5864
  } from "node:fs";
5737
- import { dirname as dirname11, join as join41, sep as sep7 } from "node:path";
5865
+ import { dirname as dirname11, join as join42, sep as sep7 } from "node:path";
5738
5866
 
5739
5867
  // src/skills-sync.ts
5740
5868
  init_config();
5741
- import { existsSync as existsSync30, lstatSync as lstatSync15, mkdirSync as mkdirSync10, readdirSync as readdirSync14, rmSync as rmSync13 } from "node:fs";
5742
- import { join as join40 } from "node:path";
5869
+ import { existsSync as existsSync29, lstatSync as lstatSync15, mkdirSync as mkdirSync10, readdirSync as readdirSync14, rmSync as rmSync13 } from "node:fs";
5870
+ import { join as join41 } from "node:path";
5743
5871
 
5744
5872
  // src/skills-sync.tracked.ts
5745
5873
  init_utils();
@@ -5774,9 +5902,9 @@ function copySkillsPull(src, dst, isRootPreserved) {
5774
5902
  copyExtrasFilteredPreservingBy(src, dst, isSkillExcluded, isRootPreserved);
5775
5903
  }
5776
5904
  function syncSkillsPull(ts, prePostHeads) {
5777
- const sharedSkills = join40(repoHome(), "shared", "skills");
5778
- if (!existsSync30(sharedSkills)) return;
5779
- const localSkills = join40(claudeHome(), "skills");
5905
+ const sharedSkills = join41(repoHome(), "shared", "skills");
5906
+ if (!existsSync29(sharedSkills)) return;
5907
+ const localSkills = join41(claudeHome(), "skills");
5780
5908
  backupBeforeWrite(localSkills, ts);
5781
5909
  const dstStat = lstatSync15(localSkills, { throwIfNoEntry: false });
5782
5910
  if (dstStat?.isSymbolicLink() === true) {
@@ -5787,11 +5915,11 @@ function syncSkillsPull(ts, prePostHeads) {
5787
5915
  copySkillsPull(sharedSkills, localSkills, (name) => !tracked.has(name));
5788
5916
  }
5789
5917
  function syncSkillsPush() {
5790
- const localSkills = join40(claudeHome(), "skills");
5918
+ const localSkills = join41(claudeHome(), "skills");
5791
5919
  const stat = lstatSync15(localSkills, { throwIfNoEntry: false });
5792
5920
  if (stat === void 0) return;
5793
5921
  if (stat.isSymbolicLink()) return;
5794
- const sharedSkills = join40(repoHome(), "shared", "skills");
5922
+ const sharedSkills = join41(repoHome(), "shared", "skills");
5795
5923
  copySkillsPush(localSkills, sharedSkills);
5796
5924
  }
5797
5925
 
@@ -5814,16 +5942,16 @@ function resolveSkillLocalPath(name, relPath) {
5814
5942
  if (!SAFE_SKILL_NAME.test(name) || name === "." || name === "..") return null;
5815
5943
  if (isGsdOwned(name)) return null;
5816
5944
  if (!isSafeRelPath(relPath)) return null;
5817
- const skillsRoot = join41(claudeHome(), "skills");
5818
- const skillRoot = join41(skillsRoot, name);
5819
- const localPath = join41(skillRoot, ...relPath.split("/"));
5945
+ const skillsRoot = join42(claudeHome(), "skills");
5946
+ const skillRoot = join42(skillsRoot, name);
5947
+ const localPath = join42(skillRoot, ...relPath.split("/"));
5820
5948
  if (localPath !== skillRoot && !localPath.startsWith(skillRoot + sep7)) return null;
5821
5949
  try {
5822
5950
  if (lstatSync16(localPath).isSymbolicLink()) return null;
5823
5951
  const realLocal = realpathSync6(localPath);
5824
5952
  const realRoot = realpathSync6(skillsRoot);
5825
5953
  if (!realLocal.startsWith(realRoot + sep7)) return null;
5826
- if (!statSync7(realLocal).isFile()) return null;
5954
+ if (!statSync8(realLocal).isFile()) return null;
5827
5955
  } catch {
5828
5956
  return null;
5829
5957
  }
@@ -5868,7 +5996,7 @@ function applySkillRedact(f, ts, scan = scanFile) {
5868
5996
  );
5869
5997
  }
5870
5998
  writeFileSync7(localPath, after, "utf8");
5871
- const dest = join41(repoHome(), "shared", "skills", name, ...relPath.split("/"));
5999
+ const dest = join42(repoHome(), "shared", "skills", name, ...relPath.split("/"));
5872
6000
  mkdirSync11(dirname11(dest), { recursive: true });
5873
6001
  cpSync7(localPath, dest, { force: true });
5874
6002
  return true;
@@ -5946,25 +6074,25 @@ function applyDeferredAllows(findings, state, repo) {
5946
6074
  // src/commands.push.recovery.redact.ts
5947
6075
  init_config();
5948
6076
  init_config_sharedDirs_guard();
5949
- import { cpSync as cpSync8, existsSync as existsSync33, mkdirSync as mkdirSync12 } from "node:fs";
5950
- import { dirname as dirname13, join as join44, sep as sep8 } from "node:path";
6077
+ import { cpSync as cpSync8, existsSync as existsSync32, mkdirSync as mkdirSync12 } from "node:fs";
6078
+ import { dirname as dirname13, join as join45, sep as sep8 } from "node:path";
5951
6079
 
5952
6080
  // src/commands.redact.ts
5953
6081
  init_config();
5954
- import { existsSync as existsSync32 } from "node:fs";
5955
- import { dirname as dirname12, join as join43 } from "node:path";
6082
+ import { existsSync as existsSync31 } from "node:fs";
6083
+ import { dirname as dirname12, join as join44 } from "node:path";
5956
6084
 
5957
6085
  // src/commands.redact.subtree.ts
5958
- import { existsSync as existsSync31, lstatSync as lstatSync17, readFileSync as readFileSync16, readdirSync as readdirSync15, statSync as statSync8, writeFileSync as writeFileSync8 } from "node:fs";
5959
- import { join as join42 } from "node:path";
6086
+ import { existsSync as existsSync30, lstatSync as lstatSync17, readFileSync as readFileSync16, readdirSync as readdirSync15, statSync as statSync9, writeFileSync as writeFileSync8 } from "node:fs";
6087
+ import { join as join43 } from "node:path";
5960
6088
  init_utils_fs();
5961
6089
  init_utils();
5962
6090
  function collectFiles(dir, out) {
5963
- if (!existsSync31(dir)) return;
6091
+ if (!existsSync30(dir)) return;
5964
6092
  const st = lstatSync17(dir);
5965
6093
  if (!st.isDirectory()) return;
5966
6094
  for (const entry of readdirSync15(dir)) {
5967
- const abs = join42(dir, entry);
6095
+ const abs = join43(dir, entry);
5968
6096
  const lst = lstatSync17(abs);
5969
6097
  if (lst.isSymbolicLink()) continue;
5970
6098
  if (lst.isDirectory()) {
@@ -5979,7 +6107,7 @@ function listSubtreeFiles(sessionDir) {
5979
6107
  collectFiles(sessionDir, out);
5980
6108
  return out.sort((a, b) => a.localeCompare(b));
5981
6109
  }
5982
- function newestSubtreeMtimeMs(mainPath, subtreeFiles, statMtime = (p) => statSync8(p).mtimeMs) {
6110
+ function newestSubtreeMtimeMs(mainPath, subtreeFiles, statMtime = (p) => statSync9(p).mtimeMs) {
5983
6111
  let newest = statMtime(mainPath);
5984
6112
  for (const filePath of subtreeFiles) {
5985
6113
  const t = statMtime(filePath);
@@ -5988,7 +6116,7 @@ function newestSubtreeMtimeMs(mainPath, subtreeFiles, statMtime = (p) => statSyn
5988
6116
  return newest;
5989
6117
  }
5990
6118
  function isSubtreeActive(mainPath, subtreeFiles, now) {
5991
- const subtreeMtime = newestSubtreeMtimeMs(mainPath, subtreeFiles, (p) => statSync8(p).mtimeMs);
6119
+ const subtreeMtime = newestSubtreeMtimeMs(mainPath, subtreeFiles, (p) => statSync9(p).mtimeMs);
5992
6120
  return isRecentlyModified(subtreeMtime, now);
5993
6121
  }
5994
6122
  function applySubtreeRedactions(mainPath, mainFindings, subtreeFiles, rule, ts, scan, dryRun) {
@@ -6074,15 +6202,15 @@ init_utils_json();
6074
6202
  init_utils();
6075
6203
  function resolveLiveTranscript(id) {
6076
6204
  try {
6077
- const mapPath = join43(repoHome(), "path-map.json");
6078
- if (!existsSync32(mapPath)) return null;
6205
+ const mapPath = join44(repoHome(), "path-map.json");
6206
+ if (!existsSync31(mapPath)) return null;
6079
6207
  const projects = readJson(mapPath).projects;
6080
6208
  const claude = claudeHome();
6081
6209
  for (const hostMap of Object.values(projects)) {
6082
6210
  const abs = hostMap[HOST];
6083
6211
  if (abs === void 0) continue;
6084
- const live = join43(claude, "projects", encodePath(abs), `${id}.jsonl`);
6085
- if (existsSync32(live)) return live;
6212
+ const live = join44(claude, "projects", encodePath(abs), `${id}.jsonl`);
6213
+ if (existsSync31(live)) return live;
6086
6214
  }
6087
6215
  return null;
6088
6216
  } catch {
@@ -6102,17 +6230,17 @@ function cmdRedact(opts, nowMs = Date.now, scan = scanFile) {
6102
6230
  }
6103
6231
  const repo = repoHome();
6104
6232
  const backup = backupBase();
6105
- if (!existsSync32(repo)) die(`repo not cloned at ${repo}`);
6233
+ if (!existsSync31(repo)) die(`repo not cloned at ${repo}`);
6106
6234
  const handle = acquireLock("redact");
6107
6235
  if (handle === null) process.exit(0);
6108
6236
  try {
6109
6237
  const localPath = resolveLiveTranscript(id);
6110
- if (localPath === null || !existsSync32(localPath)) {
6238
+ if (localPath === null || !existsSync31(localPath)) {
6111
6239
  fail(`could not resolve local transcript for session ${id} on this host`);
6112
6240
  process.exitCode = 1;
6113
6241
  return;
6114
6242
  }
6115
- const sessionDir = join43(dirname12(localPath), id);
6243
+ const sessionDir = join44(dirname12(localPath), id);
6116
6244
  const subtreeFiles = listSubtreeFiles(sessionDir);
6117
6245
  if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
6118
6246
  log(
@@ -6173,8 +6301,8 @@ function resolveStagedDir(localPath, map, claude, repo) {
6173
6301
  assertSafeLogical(logical);
6174
6302
  const abs = hostMap[HOST];
6175
6303
  if (abs === void 0) continue;
6176
- if (localPath.startsWith(join44(claude, "projects", encodePath(abs)) + sep8)) {
6177
- return join44(repo, "shared", "projects", logical);
6304
+ if (localPath.startsWith(join45(claude, "projects", encodePath(abs)) + sep8)) {
6305
+ return join45(repo, "shared", "projects", logical);
6178
6306
  }
6179
6307
  }
6180
6308
  return null;
@@ -6184,7 +6312,7 @@ function preflightRedactable(f, map, nowMs) {
6184
6312
  if (sid === null) return "a finding has no resolvable session id (not a session transcript)";
6185
6313
  const localPath = resolveLiveTranscript(sid);
6186
6314
  if (localPath === null) return `session ${sid}: local transcript not found`;
6187
- const sessionDir = join44(dirname13(localPath), sid);
6315
+ const sessionDir = join45(dirname13(localPath), sid);
6188
6316
  const subtreeFiles = listSubtreeFiles(sessionDir);
6189
6317
  if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
6190
6318
  return `session ${sid}: looks active (modified within the last 5 minutes)`;
@@ -6213,7 +6341,7 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
6213
6341
  `could not locate the local transcript for session ${sid}; choose Skip or Drop session.`
6214
6342
  );
6215
6343
  }
6216
- const sessionDir = join44(dirname13(localPath), sid);
6344
+ const sessionDir = join45(dirname13(localPath), sid);
6217
6345
  const subtreeFiles = listSubtreeFiles(sessionDir);
6218
6346
  if (isSubtreeActive(localPath, subtreeFiles, nowMs())) {
6219
6347
  return refuse(
@@ -6246,9 +6374,9 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
6246
6374
  );
6247
6375
  }
6248
6376
  mkdirSync12(stagedProjectDir, { recursive: true });
6249
- cpSync8(localPath, join44(stagedProjectDir, `${sid}.jsonl`), { force: true });
6250
- if (existsSync33(sessionDir)) {
6251
- cpSync8(sessionDir, join44(stagedProjectDir, sid), { force: true, recursive: true });
6377
+ cpSync8(localPath, join45(stagedProjectDir, `${sid}.jsonl`), { force: true });
6378
+ if (existsSync32(sessionDir)) {
6379
+ cpSync8(sessionDir, join45(stagedProjectDir, sid), { force: true, recursive: true });
6252
6380
  }
6253
6381
  return true;
6254
6382
  }
@@ -6256,14 +6384,14 @@ function applyRedact(f, ts, map, nowMs, scan = scanFile) {
6256
6384
  // src/commands.push.recovery.drop.ts
6257
6385
  init_config();
6258
6386
  import { rmSync as rmSync14 } from "node:fs";
6259
- import { join as join45 } from "node:path";
6387
+ import { join as join46 } from "node:path";
6260
6388
  function dropSessionFromStaged(sid, map) {
6261
6389
  const logicals = Object.keys(map.projects);
6262
6390
  if (logicals.length === 0) return false;
6263
6391
  const repo = repoHome();
6264
6392
  for (const logical of logicals) {
6265
- const jsonl = join45(repo, "shared", "projects", logical, `${sid}.jsonl`);
6266
- const dir = join45(repo, "shared", "projects", logical, sid);
6393
+ const jsonl = join46(repo, "shared", "projects", logical, `${sid}.jsonl`);
6394
+ const dir = join46(repo, "shared", "projects", logical, sid);
6267
6395
  rmSync14(jsonl, { force: true });
6268
6396
  rmSync14(dir, { recursive: true, force: true });
6269
6397
  }
@@ -6748,7 +6876,7 @@ function applyThenRescan(scanVerdict, repoHome2) {
6748
6876
  return next;
6749
6877
  }
6750
6878
  function allowThenRescan(append, scanVerdict, repoHome2) {
6751
- const ignPath = join46(repoHome2, ".gitleaksignore");
6879
+ const ignPath = join47(repoHome2, ".gitleaksignore");
6752
6880
  let before;
6753
6881
  try {
6754
6882
  before = readFileSync18(ignPath, "utf8");
@@ -6854,7 +6982,7 @@ function writeAnimatedDone(out, label, ms, useTTY) {
6854
6982
  `);
6855
6983
  }
6856
6984
  function resolveWorkerPath(deps = {}) {
6857
- const check = deps.existsSyncFn ?? existsSync34;
6985
+ const check = deps.existsSyncFn ?? existsSync33;
6858
6986
  const base = deps.baseUrl ?? import.meta.url;
6859
6987
  const mjs = fileURLToPath4(new URL("./nomad.worker.mjs", base));
6860
6988
  if (check(mjs)) return mjs;
@@ -6921,8 +7049,8 @@ function withSpinner(label, fn, deps) {
6921
7049
  // src/commands.doctor.gitleaks-version.ts
6922
7050
  init_color();
6923
7051
  import { execFileSync as execFileSync15 } from "node:child_process";
6924
- import { existsSync as existsSync35 } from "node:fs";
6925
- import { join as join47 } from "node:path";
7052
+ import { existsSync as existsSync34 } from "node:fs";
7053
+ import { join as join48 } from "node:path";
6926
7054
  init_config();
6927
7055
  var SEMVER_MAJOR_MINOR = /^(\d+)\.(\d+)\.\d+$/;
6928
7056
  var GITLEAKS_TIMEOUT_MS = 5e3;
@@ -6931,7 +7059,7 @@ function majorMinorOf(value) {
6931
7059
  return m === null ? null : [m[1], m[2]];
6932
7060
  }
6933
7061
  function readGitleaksVersion(run, tomlExists) {
6934
- const tomlPath = join47(repoHome(), ".gitleaks.toml");
7062
+ const tomlPath = join48(repoHome(), ".gitleaks.toml");
6935
7063
  const args = ["version"];
6936
7064
  if (tomlExists(tomlPath)) args.push("--config", tomlPath);
6937
7065
  try {
@@ -6943,7 +7071,7 @@ function readGitleaksVersion(run, tomlExists) {
6943
7071
  return null;
6944
7072
  }
6945
7073
  }
6946
- function reportGitleaksVersionCheck(section2, run = execFileSync15, tomlExists = existsSync35) {
7074
+ function reportGitleaksVersionCheck(section2, run = execFileSync15, tomlExists = existsSync34) {
6947
7075
  const raw = readGitleaksVersion(run, tomlExists);
6948
7076
  if (raw === null) return;
6949
7077
  const local = majorMinorOf(raw);
@@ -7200,8 +7328,8 @@ function gatherDoctorSections(opts) {
7200
7328
  reportLongPathsCheck(host);
7201
7329
  reportCrlfGuardCheck(host);
7202
7330
  const links = section("Shared links");
7203
- const mapPath = join48(repoHome(), "path-map.json");
7204
- const rawMap = existsSync36(mapPath) ? readJsonSafe(mapPath, mapPath, links) : null;
7331
+ const mapPath = join49(repoHome(), "path-map.json");
7332
+ const rawMap = existsSync35(mapPath) ? readJsonSafe(mapPath, mapPath, links) : null;
7205
7333
  const map = rawMap ?? { projects: {} };
7206
7334
  reportSharedLinks(links, map);
7207
7335
  reportDroppedNamesMigration(links);
@@ -7299,8 +7427,8 @@ function parseDoctorArgs(args) {
7299
7427
  // src/commands.drop-session.ts
7300
7428
  init_config();
7301
7429
  import { execFileSync as execFileSync20 } from "node:child_process";
7302
- import { existsSync as existsSync38, readdirSync as readdirSync16, statSync as statSync9 } from "node:fs";
7303
- import { join as join50, relative as relative7 } from "node:path";
7430
+ import { existsSync as existsSync37, readdirSync as readdirSync16, statSync as statSync10 } from "node:fs";
7431
+ import { join as join51, relative as relative7 } from "node:path";
7304
7432
 
7305
7433
  // src/commands.drop-session.git.ts
7306
7434
  import { execFileSync as execFileSync19 } from "node:child_process";
@@ -7343,8 +7471,8 @@ function isInIndex(rel, repo) {
7343
7471
  init_config();
7344
7472
  init_utils();
7345
7473
  init_utils_json();
7346
- import { existsSync as existsSync37 } from "node:fs";
7347
- import { join as join49 } from "node:path";
7474
+ import { existsSync as existsSync36 } from "node:fs";
7475
+ import { join as join50 } from "node:path";
7348
7476
  var SHARED_PROJECT_LOGICAL = /^shared\/projects\/([^/]+)\//;
7349
7477
  function reportScrubHint(id, matches) {
7350
7478
  const live = resolveLiveTranscript2(id, matches);
@@ -7360,8 +7488,8 @@ function reportScrubHint(id, matches) {
7360
7488
  }
7361
7489
  function resolveLiveTranscript2(id, matches) {
7362
7490
  try {
7363
- const mapPath = join49(repoHome(), "path-map.json");
7364
- if (!existsSync37(mapPath)) return null;
7491
+ const mapPath = join50(repoHome(), "path-map.json");
7492
+ if (!existsSync36(mapPath)) return null;
7365
7493
  const projects = readJson(mapPath).projects;
7366
7494
  const claude = claudeHome();
7367
7495
  for (const rel of matches) {
@@ -7369,8 +7497,8 @@ function resolveLiveTranscript2(id, matches) {
7369
7497
  if (logical === void 0) continue;
7370
7498
  const abs = projects[logical]?.[HOST];
7371
7499
  if (abs === void 0) continue;
7372
- const live = join49(claude, "projects", encodePath(abs), `${id}.jsonl`);
7373
- if (existsSync37(live)) return live;
7500
+ const live = join50(claude, "projects", encodePath(abs), `${id}.jsonl`);
7501
+ if (existsSync36(live)) return live;
7374
7502
  }
7375
7503
  return null;
7376
7504
  } catch {
@@ -7386,12 +7514,12 @@ function cmdDropSession(id) {
7386
7514
  process.exit(1);
7387
7515
  }
7388
7516
  const repo = repoHome();
7389
- if (!existsSync38(repo)) die(`repo not cloned at ${repo}`);
7517
+ if (!existsSync37(repo)) die(`repo not cloned at ${repo}`);
7390
7518
  const handle = acquireLock("drop-session");
7391
7519
  if (handle === null) process.exit(0);
7392
7520
  try {
7393
- const repoProjects = join50(repo, "shared", "projects");
7394
- if (!existsSync38(repoProjects)) {
7521
+ const repoProjects = join51(repo, "shared", "projects");
7522
+ if (!existsSync37(repoProjects)) {
7395
7523
  throw new NomadFatal(`no staged session matches ${id}`);
7396
7524
  }
7397
7525
  const matches = collectMatches(repoProjects, id, repo);
@@ -7414,12 +7542,12 @@ function cmdDropSession(id) {
7414
7542
  function collectMatches(repoProjects, id, repo) {
7415
7543
  const matches = [];
7416
7544
  for (const logical of readdirSync16(repoProjects)) {
7417
- const candidate = join50(repoProjects, logical, `${id}.jsonl`);
7418
- if (existsSync38(candidate)) {
7545
+ const candidate = join51(repoProjects, logical, `${id}.jsonl`);
7546
+ if (existsSync37(candidate)) {
7419
7547
  matches.push(relative7(repo, candidate));
7420
7548
  }
7421
- const dir = join50(repoProjects, logical, id);
7422
- if (existsSync38(dir) && statSync9(dir).isDirectory()) {
7549
+ const dir = join51(repoProjects, logical, id);
7550
+ if (existsSync37(dir) && statSync10(dir).isDirectory()) {
7423
7551
  const dirRel = relative7(repo, dir);
7424
7552
  const staged = expandStagedDir(dirRel, repo);
7425
7553
  if (staged.length > 0) matches.push(...staged);
@@ -7455,8 +7583,8 @@ function unstageOne(rel, repo) {
7455
7583
 
7456
7584
  // src/commands.pull.ts
7457
7585
  init_autostash_guard();
7458
- import { existsSync as existsSync47, mkdirSync as mkdirSync14 } from "node:fs";
7459
- import { join as join61 } from "node:path";
7586
+ import { existsSync as existsSync46, mkdirSync as mkdirSync14 } from "node:fs";
7587
+ import { join as join62 } from "node:path";
7460
7588
 
7461
7589
  // src/commands.push.sections.ts
7462
7590
  init_color();
@@ -7564,18 +7692,18 @@ init_config();
7564
7692
 
7565
7693
  // src/extras-sync.ts
7566
7694
  init_config();
7567
- import { existsSync as existsSync40, statSync as statSync10 } from "node:fs";
7568
- import { join as join53 } from "node:path";
7695
+ import { existsSync as existsSync39, statSync as statSync11 } from "node:fs";
7696
+ import { join as join54 } from "node:path";
7569
7697
  init_utils();
7570
7698
  init_utils_json();
7571
7699
 
7572
7700
  // src/extras-sync.remap.ts
7573
7701
  init_config();
7574
- import { existsSync as existsSync39, mkdirSync as mkdirSync13, readdirSync as readdirSync17, readFileSync as readFileSync19, realpathSync as realpathSync7, rmSync as rmSync16 } from "node:fs";
7575
- import { dirname as dirname14, join as join52, sep as sep11 } from "node:path";
7702
+ import { existsSync as existsSync38, mkdirSync as mkdirSync13, readdirSync as readdirSync17, readFileSync as readFileSync19, realpathSync as realpathSync7, rmSync as rmSync16 } from "node:fs";
7703
+ import { dirname as dirname14, join as join53, sep as sep11 } from "node:path";
7576
7704
 
7577
7705
  // src/extras-sync.planning-diff.ts
7578
- import { join as join51, normalize as normalize2, sep as sep10 } from "node:path";
7706
+ import { join as join52, normalize as normalize2, sep as sep10 } from "node:path";
7579
7707
  init_utils();
7580
7708
  function processRecord(fields, i, changed, deleted) {
7581
7709
  const status = fields[i];
@@ -7627,7 +7755,7 @@ function planningDeleteTargets(opts) {
7627
7755
  const { deleted } = parsePlanningDiff(raw);
7628
7756
  const logicalPrefix = "shared/extras/" + logical + "/";
7629
7757
  const prefix = logicalPrefix + ".planning/";
7630
- const planningRoot = join51(localRoot, ".planning");
7758
+ const planningRoot = join52(localRoot, ".planning");
7631
7759
  const planningRootBoundary = planningRoot + sep10;
7632
7760
  const targets = [];
7633
7761
  for (const repoPath of deleted) {
@@ -7635,7 +7763,7 @@ function planningDeleteTargets(opts) {
7635
7763
  continue;
7636
7764
  }
7637
7765
  const remainder = repoPath.slice(logicalPrefix.length);
7638
- const candidate = join51(localRoot, remainder);
7766
+ const candidate = join52(localRoot, remainder);
7639
7767
  const resolved = normalize2(candidate);
7640
7768
  if (!resolved.startsWith(planningRootBoundary)) {
7641
7769
  throw new NomadFatal(
@@ -7656,7 +7784,7 @@ function runExtrasOp(v, dryRun, paths, backup, copy) {
7656
7784
  const would = [];
7657
7785
  for (const t of eachExtrasTarget(v, counts)) {
7658
7786
  const { src, dst } = paths(t);
7659
- if (!existsSync39(src)) continue;
7787
+ if (!existsSync38(src)) continue;
7660
7788
  const item2 = `${t.logical}/${t.dirname}`;
7661
7789
  if (dryRun) {
7662
7790
  would.push(item2);
@@ -7691,7 +7819,7 @@ function isInsidePlanningRoot(parentReal, rootReal) {
7691
7819
  return parentReal === rootReal || parentReal.startsWith(rootReal + sep11);
7692
7820
  }
7693
7821
  function deletePlanningTarget(target, planningRoot, repoCounterpart) {
7694
- if (existsSync39(repoCounterpart)) return;
7822
+ if (existsSync38(repoCounterpart)) return;
7695
7823
  const parentReal = tryRealpath(dirname14(target));
7696
7824
  if (parentReal === void 0) return;
7697
7825
  const rootReal = tryRealpath(planningRoot);
@@ -7701,7 +7829,7 @@ function deletePlanningTarget(target, planningRoot, repoCounterpart) {
7701
7829
  pruneEmptyAncestors(target, planningRoot);
7702
7830
  }
7703
7831
  function localDivergesFromPreDelete(target, pre, repoRel, repo) {
7704
- if (!existsSync39(target)) return false;
7832
+ if (!existsSync38(target)) return false;
7705
7833
  try {
7706
7834
  const preBlob = gitCaptureBuffer(["show", `${pre}:${repoRel}`], repo);
7707
7835
  return !readFileSync19(target).equals(preBlob);
@@ -7746,7 +7874,7 @@ function keptDeletePreview(v, prePostHeads, repo) {
7746
7874
  return kept;
7747
7875
  }
7748
7876
  function propagatePlanningDeletes(v, ts, prePostHeads, repo) {
7749
- const repoExtras = join52(repo, "shared", "extras");
7877
+ const repoExtras = join53(repo, "shared", "extras");
7750
7878
  for (const t of eachExtrasTarget(v, { unmapped: 0, skipped: 0 })) {
7751
7879
  if (t.dirname !== ".planning") continue;
7752
7880
  let raw;
@@ -7761,14 +7889,14 @@ function propagatePlanningDeletes(v, ts, prePostHeads, repo) {
7761
7889
  }
7762
7890
  const pairs = deletePairsFor(t, raw);
7763
7891
  if (pairs.length === 0) continue;
7764
- backupExtrasWrite(join52(t.localRoot, t.dirname), ts, t.localRoot);
7765
- const planningRoot = join52(t.localRoot, ".planning");
7892
+ backupExtrasWrite(join53(t.localRoot, t.dirname), ts, t.localRoot);
7893
+ const planningRoot = join53(t.localRoot, ".planning");
7766
7894
  for (const { target, relToLocal, repoRel } of pairs) {
7767
7895
  if (localDivergesFromPreDelete(target, prePostHeads.pre, repoRel, repo)) {
7768
7896
  warn(keptDeleteWarnLine(t.logical, relToLocal));
7769
7897
  continue;
7770
7898
  }
7771
- deletePlanningTarget(target, planningRoot, join52(repoExtras, t.logical, relToLocal));
7899
+ deletePlanningTarget(target, planningRoot, join53(repoExtras, t.logical, relToLocal));
7772
7900
  }
7773
7901
  }
7774
7902
  }
@@ -7777,14 +7905,14 @@ function remapExtrasPush(ts, opts = {}) {
7777
7905
  const v = loadValidatedExtras({ missingMsg: "no path-map.json; skipping extras push" });
7778
7906
  if (v === null) return { unmapped: 0, skipped: 0, pushed: [], wouldPush: [] };
7779
7907
  const repo = repoHome();
7780
- const repoExtras = join52(repo, "shared", "extras");
7908
+ const repoExtras = join53(repo, "shared", "extras");
7781
7909
  if (!dryRun) mkdirSync13(repoExtras, { recursive: true });
7782
7910
  const { unmapped, skipped, done, would } = runExtrasOp(
7783
7911
  v,
7784
7912
  dryRun,
7785
7913
  ({ localRoot, logical, dirname: dirname15 }) => ({
7786
- src: join52(localRoot, dirname15),
7787
- dst: join52(repoExtras, logical, dirname15)
7914
+ src: join53(localRoot, dirname15),
7915
+ dst: join53(repoExtras, logical, dirname15)
7788
7916
  }),
7789
7917
  (dst) => backupRepoWrite(dst, ts, repo),
7790
7918
  // Push copy routing per extra type:
@@ -7814,8 +7942,8 @@ function remapExtrasPull(ts, opts = {}) {
7814
7942
  v,
7815
7943
  dryRun,
7816
7944
  ({ localRoot, logical, dirname: dirname15 }) => ({
7817
- src: join52(repo, "shared", "extras", logical, dirname15),
7818
- dst: join52(localRoot, dirname15)
7945
+ src: join53(repo, "shared", "extras", logical, dirname15),
7946
+ dst: join53(localRoot, dirname15)
7819
7947
  }),
7820
7948
  // Snapshot the host-side dst BEFORE the copy step touches it. Anchor on
7821
7949
  // localRoot so the backup tree mirrors the project layout.
@@ -7862,22 +7990,22 @@ function divergenceCheckExtras(ts, prePostHeads) {
7862
7990
  const v = loadValidatedExtras({});
7863
7991
  if (v === null) return 0;
7864
7992
  const counts = { unmapped: 0, skipped: 0 };
7865
- const backupRoot = join53(backupBase(), ts, "extras");
7993
+ const backupRoot = join54(backupBase(), ts, "extras");
7866
7994
  const repo = repoHome();
7867
7995
  let divergedCount = 0;
7868
7996
  for (const { logical, localRoot, dirname: dirname15 } of eachExtrasTarget(v, counts)) {
7869
- const local = join53(localRoot, dirname15);
7870
- const repoEntry = join53(repo, "shared", "extras", logical, dirname15);
7871
- if (!existsSync40(local) || !existsSync40(repoEntry)) continue;
7997
+ const local = join54(localRoot, dirname15);
7998
+ const repoEntry = join54(repo, "shared", "extras", logical, dirname15);
7999
+ if (!existsSync39(local) || !existsSync39(repoEntry)) continue;
7872
8000
  const modified = listDivergingModified(local, repoEntry);
7873
8001
  if (modified.length === 0) continue;
7874
8002
  divergedCount += modified.length;
7875
- const projectBackupRoot = join53(backupRoot, encodePath(localRoot));
8003
+ const projectBackupRoot = join54(backupRoot, encodePath(localRoot));
7876
8004
  warn(
7877
8005
  divergenceWarnLine({
7878
8006
  dirname: dirname15,
7879
8007
  logical,
7880
- isDir: statSync10(local).isDirectory(),
8008
+ isDir: statSync11(local).isDirectory(),
7881
8009
  count: modified.length,
7882
8010
  projectBackupRoot
7883
8011
  })
@@ -7895,7 +8023,7 @@ function divergenceCheckExtras(ts, prePostHeads) {
7895
8023
  // src/links.baseline.ts
7896
8024
  init_config();
7897
8025
  import { lstatSync as lstatSync18, readdirSync as readdirSync18 } from "node:fs";
7898
- import { join as join54, relative as relative8, sep as sep12 } from "node:path";
8026
+ import { join as join55, relative as relative8, sep as sep12 } from "node:path";
7899
8027
  init_utils();
7900
8028
  var SHARED_BASELINE_KIND = "shared-links-baseline/1";
7901
8029
  var SHARED_BASELINE_CONFIG_HASH = "not-applicable";
@@ -7937,7 +8065,7 @@ function collectSharedFiles(dir, claude, scan) {
7937
8065
  return;
7938
8066
  }
7939
8067
  for (const entry of entries) {
7940
- const abs = join54(dir, entry);
8068
+ const abs = join55(dir, entry);
7941
8069
  if (isDeniedName(ALWAYS_NEVER_SYNC, entry)) {
7942
8070
  scan.declined.push(baselineKey(claude, abs));
7943
8071
  continue;
@@ -7953,7 +8081,7 @@ function enumerateLocalSharedScan(map, opts = {}) {
7953
8081
  scan.declined.push(name);
7954
8082
  continue;
7955
8083
  }
7956
- addLocalPath(join54(claude, name), claude, scan);
8084
+ addLocalPath(join55(claude, name), claude, scan);
7957
8085
  }
7958
8086
  return scan;
7959
8087
  }
@@ -7965,7 +8093,7 @@ function buildSharedBaseline(map, opts = {}) {
7965
8093
  const files = {};
7966
8094
  for (const [key, st] of Object.entries(enumerateLocalSharedFiles(map, opts))) {
7967
8095
  try {
7968
- files[key] = { size: st.size, mtime: st.mtime, hash: hashFile(join54(claude, key)) };
8096
+ files[key] = { size: st.size, mtime: st.mtime, hash: hashFile(join55(claude, key)) };
7969
8097
  } catch {
7970
8098
  }
7971
8099
  }
@@ -7982,8 +8110,8 @@ function writeSharedBaseline(map, opts = {}) {
7982
8110
 
7983
8111
  // src/commands.pull.win32.ts
7984
8112
  init_color();
7985
- import { existsSync as existsSync45 } from "node:fs";
7986
- import { join as join59 } from "node:path";
8113
+ import { existsSync as existsSync44 } from "node:fs";
8114
+ import { join as join60 } from "node:path";
7987
8115
 
7988
8116
  // src/commands.pull.recovery.git.ts
7989
8117
  init_utils();
@@ -8046,8 +8174,8 @@ function gitProbe(args, repo) {
8046
8174
 
8047
8175
  // src/links.deletions.ts
8048
8176
  init_config();
8049
- import { existsSync as existsSync41, lstatSync as lstatSync19, rmSync as rmSync17 } from "node:fs";
8050
- import { join as join55, relative as relative9, resolve as resolve5, sep as sep13 } from "node:path";
8177
+ import { existsSync as existsSync40, lstatSync as lstatSync19, rmSync as rmSync17 } from "node:fs";
8178
+ import { join as join56, relative as relative9, resolve as resolve5, sep as sep13 } from "node:path";
8051
8179
  init_utils();
8052
8180
  init_utils_fs();
8053
8181
  function isUnknown(declined, key) {
@@ -8057,15 +8185,15 @@ function deletionFor(key, names, claude, sharedRoot) {
8057
8185
  const segments = key.split("/");
8058
8186
  const name = segments[0];
8059
8187
  if (!names.has(name)) return null;
8060
- if (!existsSync41(join55(claude, name))) return null;
8188
+ if (!existsSync40(join56(claude, name))) return null;
8061
8189
  if (segments.some((segment) => isDeniedName(ALWAYS_NEVER_SYNC, segment))) return null;
8062
8190
  const repoPath = resolve5(sharedRoot, key);
8063
- const rel = relative9(join55(sharedRoot, name), repoPath);
8191
+ const rel = relative9(join56(sharedRoot, name), repoPath);
8064
8192
  if (rel === "" || rel === ".." || rel.startsWith(`..${sep13}`)) return null;
8065
8193
  if (segments.some((segment) => segment === "" || segment === "." || segment === ".."))
8066
8194
  return null;
8067
- if (!existsSync41(repoPath)) return null;
8068
- return { kind: "deletion", name, localPath: join55(claude, key), repoPath };
8195
+ if (!existsSync40(repoPath)) return null;
8196
+ return { kind: "deletion", name, localPath: join56(claude, key), repoPath };
8069
8197
  }
8070
8198
  function planSharedLinkDeletions(map, opts = {}) {
8071
8199
  if (process.platform !== "win32") return [];
@@ -8073,7 +8201,7 @@ function planSharedLinkDeletions(map, opts = {}) {
8073
8201
  const baseline = readSharedBaseline();
8074
8202
  if (baseline === null) return [];
8075
8203
  const claude = claudeHome();
8076
- const sharedRoot = join55(repoHome(), "shared");
8204
+ const sharedRoot = join56(repoHome(), "shared");
8077
8205
  const linkNames = opts.linkNames ?? allSharedLinks(map);
8078
8206
  const scan = enumerateLocalSharedScan(map, { linkNames });
8079
8207
  const present = new Set(Object.keys(scan.files).map((key) => key.toLowerCase()));
@@ -8107,8 +8235,8 @@ function applySharedLinkDeletions(map, ts, opts = {}) {
8107
8235
 
8108
8236
  // src/links.mirror.ts
8109
8237
  init_config();
8110
- import { existsSync as existsSync42, lstatSync as lstatSync20, rmSync as rmSync18 } from "node:fs";
8111
- import { join as join56 } from "node:path";
8238
+ import { existsSync as existsSync41, lstatSync as lstatSync20, rmSync as rmSync18, statSync as statSync12 } from "node:fs";
8239
+ import { join as join57 } from "node:path";
8112
8240
  init_utils();
8113
8241
  init_utils_fs();
8114
8242
  function emitMirror(onPreview, name, localPath, repoPath) {
@@ -8122,29 +8250,50 @@ function emitMirrorWet(onPreview, name, localPath, repoPath) {
8122
8250
  if (onPreview) onPreview({ kind: "mirror", name, localPath, repoPath });
8123
8251
  }
8124
8252
  function notShared(target) {
8125
- return !existsSync42(target);
8253
+ return !existsSync41(target);
8254
+ }
8255
+ function warnUnusableSharedTarget(name, dryRun, state) {
8256
+ const reason = state === "dangling" ? `shared/${name} does not resolve to anything usable in the sync repo. Remove it, or restore what it points at` : `shared/${name} could not be read in the sync repo, so whether it is usable could not be determined. Check its permissions there`;
8257
+ if (dryRun) {
8258
+ warn(`${name} would not be captured into shared/: ${reason}`);
8259
+ return;
8260
+ }
8261
+ warn(`${name} was not captured into shared/ this run: ${reason}, then run \`nomad push\` again`);
8262
+ }
8263
+ function warnUnreadableLocalName(name, target, err, dryRun) {
8264
+ const compoundState = classifyPresence(target);
8265
+ if (isUnusableTarget(compoundState)) {
8266
+ warnUnusableSharedTarget(name, dryRun, compoundState);
8267
+ return;
8268
+ }
8269
+ if (notShared(target)) return;
8270
+ if (dryRun) {
8271
+ warn(
8272
+ `${name} could not be read (${errorText(err)}), so nothing was captured for it and nothing was written. A pull that captures shared edits would skip it too. Check its permissions, or whether another program has it open`
8273
+ );
8274
+ return;
8275
+ }
8276
+ warn(
8277
+ `${name} could not be read (${errorText(err)}), so it was left out of shared/ this run. Check its permissions, or whether another program has it open`
8278
+ );
8126
8279
  }
8127
8280
  function mirrorOneSharedName(name, claude, repo, policy, opts) {
8128
- const localPath = join56(claude, name);
8129
- const target = join56(repo, "shared", name);
8281
+ const localPath = join57(claude, name);
8282
+ const target = join57(repo, "shared", name);
8130
8283
  let stat;
8131
8284
  try {
8132
8285
  stat = lstatSync20(localPath, { throwIfNoEntry: false });
8133
8286
  } catch (err) {
8134
- if (notShared(target)) return;
8135
- if (opts.dryRun === true) {
8136
- warn(
8137
- `${name} could not be read (${errorText(err)}), so nothing was captured for it and nothing was written. A pull that captures shared edits would skip it too. Check its permissions, or whether another program has it open`
8138
- );
8139
- return;
8140
- }
8141
- warn(
8142
- `${name} could not be read (${errorText(err)}), so it was left out of shared/ this run. Check its permissions, or whether another program has it open`
8143
- );
8287
+ warnUnreadableLocalName(name, target, err, opts.dryRun === true);
8144
8288
  return;
8145
8289
  }
8146
8290
  if (stat === void 0) return;
8147
8291
  if (stat.isSymbolicLink()) return;
8292
+ const targetState = classifyPresence(target);
8293
+ if (isUnusableTarget(targetState)) {
8294
+ warnUnusableSharedTarget(name, opts.dryRun === true, targetState);
8295
+ return;
8296
+ }
8148
8297
  if (notShared(target)) return;
8149
8298
  if (opts.dryRun === true) {
8150
8299
  emitMirror(opts.onPreview, name, localPath, target);
@@ -8158,11 +8307,48 @@ function mirrorOneSharedName(name, claude, repo, policy, opts) {
8158
8307
  }
8159
8308
  emitMirrorWet(opts.onPreview, name, localPath, target);
8160
8309
  }
8310
+ function warnUnusableSharedDir(dryRun, state) {
8311
+ const reason = state === "dangling" ? "shared/ does not resolve to anything usable in the sync repo. Remove it, or restore what it points at" : "shared/ could not be read in the sync repo, so whether it is usable could not be determined. Check its permissions there";
8312
+ if (dryRun) {
8313
+ warn(`no shared name would be captured into shared/: ${reason}`);
8314
+ return;
8315
+ }
8316
+ warn(
8317
+ `no shared name was captured into shared/ this run: ${reason}, then run \`nomad push\` again`
8318
+ );
8319
+ }
8320
+ function resolvesToDirectory(p) {
8321
+ try {
8322
+ return statSync12(p).isDirectory();
8323
+ } catch {
8324
+ return false;
8325
+ }
8326
+ }
8327
+ function warnSharedNotADirectory(dryRun) {
8328
+ const reason = "shared/ in the sync repo is not a directory, so there is nowhere to capture names into. Replace it with the shared/ directory the repo expects";
8329
+ if (dryRun) {
8330
+ warn(`no shared name would be captured into shared/: ${reason}`);
8331
+ return;
8332
+ }
8333
+ warn(
8334
+ `no shared name was captured into shared/ this run: ${reason}, then run \`nomad push\` again`
8335
+ );
8336
+ }
8161
8337
  function mirrorSharedNames(map, policy, opts = {}) {
8162
8338
  if (process.platform !== "win32") return;
8163
8339
  if (map === null) return;
8164
8340
  const claude = claudeHome();
8165
8341
  const repo = repoHome();
8342
+ const sharedPath = join57(repo, "shared");
8343
+ const sharedState = classifyPresence(sharedPath);
8344
+ if (isUnusableTarget(sharedState)) {
8345
+ warnUnusableSharedDir(opts.dryRun === true, sharedState);
8346
+ return;
8347
+ }
8348
+ if (sharedState === "resolves" && !resolvesToDirectory(sharedPath)) {
8349
+ warnSharedNotADirectory(opts.dryRun === true);
8350
+ return;
8351
+ }
8166
8352
  const linkNames = opts.linkNames ?? allSharedLinks(map);
8167
8353
  for (const name of linkNames) {
8168
8354
  mirrorOneSharedName(name, claude, repo, policy, opts);
@@ -8182,7 +8368,7 @@ function presentAt(abs) {
8182
8368
  }
8183
8369
  }
8184
8370
  function removeUntrackedDenied(repo, path, segment, ts) {
8185
- const abs = join56(repo, path);
8371
+ const abs = join57(repo, path);
8186
8372
  const denied = `the path segment "${segment}" is on the never-sync list`;
8187
8373
  if (!presentAt(abs)) {
8188
8374
  warn(
@@ -8190,7 +8376,7 @@ function removeUntrackedDenied(repo, path, segment, ts) {
8190
8376
  );
8191
8377
  return;
8192
8378
  }
8193
- const snapshotted = existsSync42(abs);
8379
+ const snapshotted = existsSync41(abs);
8194
8380
  try {
8195
8381
  backupRepoWrite(abs, ts, repo);
8196
8382
  } catch (err) {
@@ -8226,7 +8412,7 @@ function reportTrackedDenied(repo, path, segment) {
8226
8412
  );
8227
8413
  return;
8228
8414
  }
8229
- if (!existsSync42(join56(repo, path))) return;
8415
+ if (!existsSync41(join57(repo, path))) return;
8230
8416
  warn(
8231
8417
  `${path} is tracked and has changes against HEAD: ${denied}. Nothing was changed. Run "git checkout HEAD -- ${path}" to put the committed content back, or move the file outside shared/ if you want to keep it. Neither of those takes the committed copy out of the repo: "git rm -- ${path}" and a commit does that going forward, and if it holds a real secret, rotate it and rewrite history, because nomad only changes your local worktree and index and cannot scrub what a previous push already sent to the remote`
8232
8418
  );
@@ -8244,8 +8430,8 @@ function revertDeniedMirrorPaths(repo, status, ts) {
8244
8430
 
8245
8431
  // src/preview.ts
8246
8432
  init_config();
8247
- import { existsSync as existsSync44 } from "node:fs";
8248
- import { join as join58 } from "node:path";
8433
+ import { existsSync as existsSync43 } from "node:fs";
8434
+ import { join as join59 } from "node:path";
8249
8435
 
8250
8436
  // node_modules/diff/libesm/diff/base.js
8251
8437
  var Diff = class {
@@ -8520,16 +8706,16 @@ function diffLinesToUnified(oldStr, newStr) {
8520
8706
 
8521
8707
  // src/preview.skills.ts
8522
8708
  init_config();
8523
- import { existsSync as existsSync43, readdirSync as readdirSync19 } from "node:fs";
8524
- import { join as join57 } from "node:path";
8709
+ import { existsSync as existsSync42, readdirSync as readdirSync19 } from "node:fs";
8710
+ import { join as join58 } from "node:path";
8525
8711
  function buildSkillsPreviewSection() {
8526
8712
  const s = section("Skills");
8527
- const sharedSkills = join57(repoHome(), "shared", "skills");
8528
- if (!existsSync43(sharedSkills)) return s;
8713
+ const sharedSkills = join58(repoHome(), "shared", "skills");
8714
+ if (!existsSync42(sharedSkills)) return s;
8529
8715
  const sharedNames = readdirSync19(sharedSkills, { encoding: "utf8" }).filter((name) => !isSkillExcluded(name)).sort((a, b) => a.localeCompare(b, "en"));
8530
8716
  for (const name of sharedNames) addItem(s, name);
8531
- const localSkills = join57(claudeHome(), "skills");
8532
- const localOnly = existsSync43(localSkills) ? readdirSync19(localSkills, { encoding: "utf8" }).filter(
8717
+ const localSkills = join58(claudeHome(), "skills");
8718
+ const localOnly = existsSync42(localSkills) ? readdirSync19(localSkills, { encoding: "utf8" }).filter(
8533
8719
  (name) => !isSkillExcluded(name) && !sharedNames.includes(name)
8534
8720
  ).length : 0;
8535
8721
  if (localOnly > 0) {
@@ -8551,7 +8737,7 @@ function diffJsonStrings(currentJsonText, newJsonText) {
8551
8737
  return lines.join("\n");
8552
8738
  }
8553
8739
  function readJsonOrNull(path) {
8554
- if (!existsSync44(path)) return null;
8740
+ if (!existsSync43(path)) return null;
8555
8741
  try {
8556
8742
  return readJson(path);
8557
8743
  } catch {
@@ -8565,12 +8751,12 @@ function previewSettings(basePath, hostPath, settingsPath) {
8565
8751
  }
8566
8752
  const notes = [];
8567
8753
  const hostOverrides = readJsonOrNull(hostPath);
8568
- if (hostOverrides === null && existsSync44(hostPath)) {
8754
+ if (hostOverrides === null && existsSync43(hostPath)) {
8569
8755
  notes.push(`malformed hosts/${HOST}.json; ignoring overrides`);
8570
8756
  }
8571
8757
  const merged = stripGsdHookEntries(deepMerge(base, hostOverrides ?? {}));
8572
8758
  const current = readJsonOrNull(settingsPath);
8573
- if (current === null && existsSync44(settingsPath)) {
8759
+ if (current === null && existsSync43(settingsPath)) {
8574
8760
  return { diff: "", notes: [...notes, "malformed; skipping diff"] };
8575
8761
  }
8576
8762
  const strippedCurrent = stripGsdHookEntries(current ?? {});
@@ -8637,9 +8823,9 @@ function computePreview(ts, map, verb = "pull", plans) {
8637
8823
  onPreview: (e) => addItem(links, formatLinkRow(e))
8638
8824
  });
8639
8825
  const settingsResult = previewSettings(
8640
- join58(repo, "shared", "settings.base.json"),
8641
- join58(repo, "hosts", `${HOST}.json`),
8642
- join58(claude, "settings.json")
8826
+ join59(repo, "shared", "settings.base.json"),
8827
+ join59(repo, "hosts", `${HOST}.json`),
8828
+ join59(claude, "settings.json")
8643
8829
  );
8644
8830
  const settingsSection = buildSettingsSectionForPreview(settingsResult);
8645
8831
  const sessions = section("Sessions");
@@ -8655,7 +8841,7 @@ function computePreview(ts, map, verb = "pull", plans) {
8655
8841
  const extras = section("Extras");
8656
8842
  let extrasSkipped = 0;
8657
8843
  let extrasUnmapped = 0;
8658
- if (existsSync44(join58(repo, "path-map.json")) && existsSync44(join58(repo, "shared", "extras"))) {
8844
+ if (existsSync43(join59(repo, "path-map.json")) && existsSync43(join59(repo, "shared", "extras"))) {
8659
8845
  const extrasResult = remapExtrasPull(ts, { dryRun: true });
8660
8846
  for (const entry of extrasResult.wouldPull) {
8661
8847
  addItem(extras, entry);
@@ -8676,7 +8862,7 @@ function computePreview(ts, map, verb = "pull", plans) {
8676
8862
  init_utils();
8677
8863
  init_utils_json();
8678
8864
  function readMapForMirror(mapPath) {
8679
- if (!existsSync45(mapPath)) return { projects: {} };
8865
+ if (!existsSync44(mapPath)) return { projects: {} };
8680
8866
  try {
8681
8867
  return readPathMap(mapPath);
8682
8868
  } catch {
@@ -8723,7 +8909,7 @@ function reconcileSharedLinksBeforePull(repo, ts) {
8723
8909
  let namesDerived = false;
8724
8910
  let derivedSharedDirs;
8725
8911
  try {
8726
- const map = readMapForMirror(join59(repo, "path-map.json"));
8912
+ const map = readMapForMirror(join60(repo, "path-map.json"));
8727
8913
  if (map !== null) {
8728
8914
  linkNames = allSharedLinks(map);
8729
8915
  namesDerived = true;
@@ -8762,7 +8948,7 @@ function buildMirrorSection(events, discard) {
8762
8948
  function describeSkippedMirrorDiscard(repo, ts) {
8763
8949
  if (process.platform !== "win32") return null;
8764
8950
  try {
8765
- const map = readMapForMirror(join59(repo, "path-map.json"));
8951
+ const map = readMapForMirror(join60(repo, "path-map.json"));
8766
8952
  const linkNames = map !== null ? allSharedLinks(map, { quiet: true }) : void 0;
8767
8953
  const captures = [];
8768
8954
  stageLocalSharedEdits(map, ts, {
@@ -8771,13 +8957,13 @@ function describeSkippedMirrorDiscard(repo, ts) {
8771
8957
  linkNames
8772
8958
  });
8773
8959
  if (captures.length === 0) return null;
8774
- return { count: captures.length, backupPath: join59(backupBase(), ts) };
8960
+ return { count: captures.length, backupPath: join60(backupBase(), ts) };
8775
8961
  } catch {
8776
8962
  return null;
8777
8963
  }
8778
8964
  }
8779
8965
  function planSharedReconcileBeforePull(repo, ts) {
8780
- const map = readMapForMirror(join59(repo, "path-map.json"));
8966
+ const map = readMapForMirror(join60(repo, "path-map.json"));
8781
8967
  const captures = [];
8782
8968
  const linkNames = process.platform === "win32" && map !== null ? allSharedLinks(map) : void 0;
8783
8969
  stageLocalSharedEdits(map, ts, { dryRun: true, onPreview: (e) => captures.push(e), linkNames });
@@ -8792,8 +8978,8 @@ function planSharedReconcileBeforePull(repo, ts) {
8792
8978
  // src/commands.pull.collision.ts
8793
8979
  init_config();
8794
8980
  init_exit_codes();
8795
- import { existsSync as existsSync46, lstatSync as lstatSync21, readFileSync as readFileSync20, rmSync as rmSync19 } from "node:fs";
8796
- import { join as join60 } from "node:path";
8981
+ import { existsSync as existsSync45, lstatSync as lstatSync21, readFileSync as readFileSync20, rmSync as rmSync19 } from "node:fs";
8982
+ import { join as join61 } from "node:path";
8797
8983
  init_utils();
8798
8984
  var SHARED_PREFIX = /^shared\//;
8799
8985
  var EXTENSION = /(\.[^.]+)?$/;
@@ -8849,15 +9035,15 @@ function isContainedMirrorPath(rel) {
8849
9035
  }
8850
9036
  function matchesLocalOriginal(repo, rel) {
8851
9037
  try {
8852
- const local = join60(claudeHome(), rel.replace(SHARED_PREFIX, ""));
8853
- return readFileSync20(join60(repo, rel)).equals(readFileSync20(local));
9038
+ const local = join61(claudeHome(), rel.replace(SHARED_PREFIX, ""));
9039
+ return readFileSync20(join61(repo, rel)).equals(readFileSync20(local));
8854
9040
  } catch {
8855
9041
  return false;
8856
9042
  }
8857
9043
  }
8858
9044
  function removeMirroredCopies(repo, repoRelPaths) {
8859
9045
  for (const rel of repoRelPaths.filter(isContainedMirrorPath)) {
8860
- const abs = join60(repo, rel);
9046
+ const abs = join61(repo, rel);
8861
9047
  try {
8862
9048
  if (lstatSync21(abs, { throwIfNoEntry: false })?.isFile() !== true) continue;
8863
9049
  if (!matchesLocalOriginal(repo, rel)) continue;
@@ -8866,7 +9052,7 @@ function removeMirroredCopies(repo, repoRelPaths) {
8866
9052
  warn(`could not remove nomad's copy at ${abs}: ${err.message}`);
8867
9053
  }
8868
9054
  }
8869
- return repoRelPaths.every((rel) => !existsSync46(join60(repo, rel)));
9055
+ return repoRelPaths.every((rel) => !existsSync45(join61(repo, rel)));
8870
9056
  }
8871
9057
  function pullWithCollisionRunbook(repo, mirrored) {
8872
9058
  try {
@@ -9073,7 +9259,7 @@ function runPullCore(opts = {}) {
9073
9259
  try {
9074
9260
  return runPullWithBackupTs(ts, opts);
9075
9261
  } finally {
9076
- discardEmptyBackupDir(join61(backup, ts));
9262
+ discardEmptyBackupDir(join62(backup, ts));
9077
9263
  }
9078
9264
  }
9079
9265
  function runPullWithBackupTs(ts, opts) {
@@ -9084,7 +9270,7 @@ function runPullWithBackupTs(ts, opts) {
9084
9270
  const backup = backupBase();
9085
9271
  const recovered = handleWedge(repo, forceRemote);
9086
9272
  if (!dryRun) {
9087
- const backupRoot = join61(backup, ts);
9273
+ const backupRoot = join62(backup, ts);
9088
9274
  try {
9089
9275
  mkdirSync14(backupRoot, { recursive: true });
9090
9276
  } catch (err) {
@@ -9107,8 +9293,8 @@ function runPullWithBackupTs(ts, opts) {
9107
9293
  pullWithCollisionRunbook(repo, mirrored);
9108
9294
  });
9109
9295
  assertNoAutostashConflict(repo, "nomad pull");
9110
- const mapPath = join61(repo, "path-map.json");
9111
- const map = existsSync47(mapPath) ? readPathMap(mapPath) : { projects: {} };
9296
+ const mapPath = join62(repo, "path-map.json");
9297
+ const map = existsSync46(mapPath) ? readPathMap(mapPath) : { projects: {} };
9112
9298
  const divergedKeptLocal = divergenceCheckExtras(ts, dryRun ? prePostHeads : void 0);
9113
9299
  if (dryRun) {
9114
9300
  computePreview(ts, map, "pull", plansAgainst(sharedPlans, map));
@@ -9135,8 +9321,8 @@ function runPullWithBackupTs(ts, opts) {
9135
9321
  }
9136
9322
  function cmdPull(opts = {}) {
9137
9323
  const repo = repoHome();
9138
- if (!existsSync47(repo)) die(`repo not cloned at ${repo}`);
9139
- if (!existsSync47(join61(repo, "shared", "settings.base.json"))) {
9324
+ if (!existsSync46(repo)) die(`repo not cloned at ${repo}`);
9325
+ if (!existsSync46(join62(repo, "shared", "settings.base.json"))) {
9140
9326
  die("repo not initialized; run 'nomad init' to scaffold");
9141
9327
  }
9142
9328
  const handle = acquireLock("pull");
@@ -9159,13 +9345,13 @@ function cmdPull(opts = {}) {
9159
9345
 
9160
9346
  // src/commands.push.ts
9161
9347
  init_config();
9162
- import { existsSync as existsSync51 } from "node:fs";
9163
- import { join as join66 } from "node:path";
9348
+ import { existsSync as existsSync50 } from "node:fs";
9349
+ import { join as join67 } from "node:path";
9164
9350
 
9165
9351
  // src/commands.push.selection.ts
9166
9352
  init_config();
9167
- import { existsSync as existsSync48, statSync as statSync11 } from "node:fs";
9168
- import { join as join62 } from "node:path";
9353
+ import { existsSync as existsSync47, statSync as statSync13 } from "node:fs";
9354
+ import { join as join63 } from "node:path";
9169
9355
  init_utils_json();
9170
9356
  function buildCurrentMap(map) {
9171
9357
  const current = {};
@@ -9174,10 +9360,10 @@ function buildCurrentMap(map) {
9174
9360
  for (const [, hostMap] of Object.entries(map.projects)) {
9175
9361
  const localPath = hostMap[HOST];
9176
9362
  if (!localPath) continue;
9177
- const localDir = join62(claude, "projects", encodePath(localPath));
9178
- if (!existsSync48(localDir)) continue;
9363
+ const localDir = join63(claude, "projects", encodePath(localPath));
9364
+ if (!existsSync47(localDir)) continue;
9179
9365
  for (const f of enumerateSourceFiles(localDir)) {
9180
- const st = statSync11(f);
9366
+ const st = statSync13(f);
9181
9367
  current[f] = { size: st.size, mtime: st.mtimeMs };
9182
9368
  }
9183
9369
  }
@@ -9206,7 +9392,7 @@ function computePushSelection(map, old, scannerVersion, configHash, fullScan) {
9206
9392
  };
9207
9393
  }
9208
9394
  function loadSelectionForPush(mapPath, old, scannerVersion, configHash, fullScan) {
9209
- const map = existsSync48(mapPath) ? readPathMap(mapPath) : null;
9395
+ const map = existsSync47(mapPath) ? readPathMap(mapPath) : null;
9210
9396
  const { selection, newManifest } = computePushSelection(
9211
9397
  map,
9212
9398
  old,
@@ -9299,14 +9485,14 @@ function enforceAllowList(statusPorcelain, map) {
9299
9485
 
9300
9486
  // src/commands.push.settings.ts
9301
9487
  init_config();
9302
- import { existsSync as existsSync49 } from "node:fs";
9303
- import { join as join63 } from "node:path";
9488
+ import { existsSync as existsSync48 } from "node:fs";
9489
+ import { join as join64 } from "node:path";
9304
9490
  init_utils();
9305
9491
  init_utils_fs();
9306
9492
  init_utils_json();
9307
9493
  function stripGsdHooksFromBase(repo, backup) {
9308
- const basePath = join63(repo, "shared", "settings.base.json");
9309
- if (!existsSync49(basePath)) return;
9494
+ const basePath = join64(repo, "shared", "settings.base.json");
9495
+ if (!existsSync48(basePath)) return;
9310
9496
  let base;
9311
9497
  try {
9312
9498
  base = readJson(basePath);
@@ -9320,14 +9506,14 @@ function stripGsdHooksFromBase(repo, backup) {
9320
9506
  writeJsonAtomic(basePath, stripped);
9321
9507
  }
9322
9508
  function reportSettingsAheadDrift(repo) {
9323
- const basePath = join63(repo, "shared", "settings.base.json");
9324
- if (!existsSync49(basePath)) return;
9325
- const settingsPath = join63(claudeHome(), "settings.json");
9326
- if (!existsSync49(settingsPath)) return;
9509
+ const basePath = join64(repo, "shared", "settings.base.json");
9510
+ if (!existsSync48(basePath)) return;
9511
+ const settingsPath = join64(claudeHome(), "settings.json");
9512
+ if (!existsSync48(settingsPath)) return;
9327
9513
  try {
9328
9514
  const base = readJson(basePath);
9329
- const hostPath = join63(repo, "hosts", `${HOST}.json`);
9330
- const overrides = existsSync49(hostPath) ? readJson(hostPath) : {};
9515
+ const hostPath = join64(repo, "hosts", `${HOST}.json`);
9516
+ const overrides = existsSync48(hostPath) ? readJson(hostPath) : {};
9331
9517
  const merged = deepMerge(base, overrides);
9332
9518
  const settings = readJson(settingsPath);
9333
9519
  const { ahead } = classifySettingsDrift(merged, settings);
@@ -9344,9 +9530,9 @@ function reportSettingsAheadDrift(repo) {
9344
9530
  // src/commands.push.guards.ts
9345
9531
  init_push_checks();
9346
9532
  init_utils();
9347
- import { join as join64, relative as relative10 } from "node:path";
9533
+ import { join as join65, relative as relative10 } from "node:path";
9348
9534
  function guardGitlinks(repo) {
9349
- const gitlinks = findGitlinks(join64(repo, "shared"));
9535
+ const gitlinks = findGitlinks(join65(repo, "shared"));
9350
9536
  if (gitlinks.length === 0) return;
9351
9537
  for (const p of gitlinks) {
9352
9538
  const rel = relative10(repo, p).replaceAll("\\", "/");
@@ -9456,9 +9642,9 @@ init_color();
9456
9642
  init_config();
9457
9643
  init_config_sharedDirs_guard();
9458
9644
  import { randomBytes as randomBytes4 } from "node:crypto";
9459
- import { copyFileSync, existsSync as existsSync50, lstatSync as lstatSync22, mkdirSync as mkdirSync15, readdirSync as readdirSync20, rmSync as rmSync20 } from "node:fs";
9645
+ import { copyFileSync, existsSync as existsSync49, lstatSync as lstatSync22, mkdirSync as mkdirSync15, readdirSync as readdirSync20, rmSync as rmSync20 } from "node:fs";
9460
9646
  import { homedir as homedir7 } from "node:os";
9461
- import { join as join65, relative as relative11, sep as sep14 } from "node:path";
9647
+ import { join as join66, relative as relative11, sep as sep14 } from "node:path";
9462
9648
  init_push_leak_verdict();
9463
9649
  init_push_gitleaks();
9464
9650
  init_utils_fs();
@@ -9470,7 +9656,7 @@ function stageSessionDir(localDir, dstDir, changed) {
9470
9656
  const matching = [...changed].filter((p) => p.startsWith(prefix));
9471
9657
  if (matching.length === 0) return false;
9472
9658
  for (const src of matching) {
9473
- copyFileAtomic(src, join65(dstDir, relative11(localDir, src)));
9659
+ copyFileAtomic(src, join66(dstDir, relative11(localDir, src)));
9474
9660
  }
9475
9661
  return true;
9476
9662
  }
@@ -9486,14 +9672,14 @@ function stageSessions(tmpRoot, map, changed) {
9486
9672
  if (!p || p === "TBD") continue;
9487
9673
  reverse.set(encodePath(p), logical);
9488
9674
  }
9489
- const localProjects = join65(claudeHome(), "projects");
9490
- if (!existsSync50(localProjects)) return 0;
9675
+ const localProjects = join66(claudeHome(), "projects");
9676
+ if (!existsSync49(localProjects)) return 0;
9491
9677
  let staged = 0;
9492
9678
  for (const dir of readdirSync20(localProjects)) {
9493
9679
  const logical = reverse.get(dir);
9494
9680
  if (!logical) continue;
9495
- const localDir = join65(localProjects, dir);
9496
- const dstDir = join65(tmpRoot, "shared", "projects", logical);
9681
+ const localDir = join66(localProjects, dir);
9682
+ const dstDir = join66(tmpRoot, "shared", "projects", logical);
9497
9683
  if (stageSessionDir(localDir, dstDir, changed)) staged++;
9498
9684
  }
9499
9685
  return staged;
@@ -9509,9 +9695,9 @@ function stageExtras(tmpRoot, map) {
9509
9695
  if (!localRoot || localRoot === "TBD") continue;
9510
9696
  for (const dirname15 of dirnames) {
9511
9697
  if (!whitelist.includes(dirname15)) continue;
9512
- const src = join65(localRoot, dirname15);
9513
- if (!existsSync50(src)) continue;
9514
- const dst = join65(tmpRoot, "shared", "extras", logical, dirname15);
9698
+ const src = join66(localRoot, dirname15);
9699
+ if (!existsSync49(src)) continue;
9700
+ const dst = join66(tmpRoot, "shared", "extras", logical, dirname15);
9515
9701
  copyExtras(src, dst);
9516
9702
  staged++;
9517
9703
  }
@@ -9519,19 +9705,19 @@ function stageExtras(tmpRoot, map) {
9519
9705
  return staged;
9520
9706
  }
9521
9707
  function stageSkills(tmpRoot) {
9522
- const localSkills = join65(claudeHome(), "skills");
9708
+ const localSkills = join66(claudeHome(), "skills");
9523
9709
  const stat = lstatSync22(localSkills, { throwIfNoEntry: false });
9524
9710
  if (stat === void 0 || stat.isSymbolicLink()) return 0;
9525
9711
  const names = readdirSync20(localSkills, { encoding: "utf8" }).filter((n) => !isSkillExcluded(n));
9526
9712
  if (names.length === 0) return 0;
9527
- copySkillsPush(localSkills, join65(tmpRoot, "shared", "skills"));
9713
+ copySkillsPush(localSkills, join66(tmpRoot, "shared", "skills"));
9528
9714
  return names.length;
9529
9715
  }
9530
9716
  function previewPushLeaks(map, opts = {}) {
9531
- const cacheDir = join65(homedir7(), ".cache", "claude-nomad");
9717
+ const cacheDir = join66(homedir7(), ".cache", "claude-nomad");
9532
9718
  mkdirSync15(cacheDir, { recursive: true });
9533
9719
  const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes4(4).toString("hex")}`;
9534
- const tmpRoot = join65(cacheDir, `push-preview-tree-${stamp}`);
9720
+ const tmpRoot = join66(cacheDir, `push-preview-tree-${stamp}`);
9535
9721
  try {
9536
9722
  const sessionCount = stageSessions(tmpRoot, map, opts.selection?.changed);
9537
9723
  const extrasCount = stageExtras(tmpRoot, map);
@@ -9539,9 +9725,9 @@ function previewPushLeaks(map, opts = {}) {
9539
9725
  if (sessionCount + extrasCount + skillCount === 0) {
9540
9726
  return { leak: false, verdictRow: NOTHING_TO_SCAN_ROW, recovery: null, findings: [] };
9541
9727
  }
9542
- const ignoreFile = join65(repoHome(), ".gitleaksignore");
9543
- if (existsSync50(ignoreFile)) {
9544
- copyFileSync(ignoreFile, join65(tmpRoot, ".gitleaksignore"));
9728
+ const ignoreFile = join66(repoHome(), ".gitleaksignore");
9729
+ if (existsSync49(ignoreFile)) {
9730
+ copyFileSync(ignoreFile, join66(tmpRoot, ".gitleaksignore"));
9545
9731
  }
9546
9732
  let findings;
9547
9733
  try {
@@ -9669,7 +9855,7 @@ async function runPushCore(opts = {}) {
9669
9855
  const scannerVersion = probeGitleaks();
9670
9856
  const configHash = computeConfigHash();
9671
9857
  const old = readManifest(manifestPath());
9672
- const mapPath = join66(repo, "path-map.json");
9858
+ const mapPath = join67(repo, "path-map.json");
9673
9859
  const { map, selection, newManifest } = loadSelectionForPush(
9674
9860
  mapPath,
9675
9861
  old,
@@ -9722,7 +9908,7 @@ async function cmdPush(opts = {}) {
9722
9908
  opts.allowRule
9723
9909
  );
9724
9910
  const repo = repoHome();
9725
- if (!existsSync51(repo)) die(`repo not cloned at ${repo}`);
9911
+ if (!existsSync50(repo)) die(`repo not cloned at ${repo}`);
9726
9912
  const handle = acquireLock("push");
9727
9913
  if (handle === null) process.exit(0);
9728
9914
  try {
@@ -9740,8 +9926,8 @@ async function cmdPush(opts = {}) {
9740
9926
  }
9741
9927
 
9742
9928
  // src/commands.sync.ts
9743
- import { existsSync as existsSync52 } from "node:fs";
9744
- import { join as join67 } from "node:path";
9929
+ import { existsSync as existsSync51 } from "node:fs";
9930
+ import { join as join68 } from "node:path";
9745
9931
  init_config();
9746
9932
  init_color();
9747
9933
  init_utils();
@@ -9882,8 +10068,8 @@ async function cmdSync(opts = {}) {
9882
10068
  const dryRun = opts.dryRun === true;
9883
10069
  const verbose = opts.verbose === true;
9884
10070
  const repo = repoHome();
9885
- if (!existsSync52(repo)) die(`repo not cloned at ${repo}`);
9886
- if (!existsSync52(join67(repo, "shared", "settings.base.json"))) {
10071
+ if (!existsSync51(repo)) die(`repo not cloned at ${repo}`);
10072
+ if (!existsSync51(join68(repo, "shared", "settings.base.json"))) {
9887
10073
  die("repo not initialized; run 'nomad init' to scaffold");
9888
10074
  }
9889
10075
  const handle = acquireLock("sync");
@@ -9959,8 +10145,8 @@ init_config();
9959
10145
  // src/crash-report.write.ts
9960
10146
  init_config();
9961
10147
  import { randomBytes as randomBytes5 } from "node:crypto";
9962
- import { mkdirSync as mkdirSync16, readdirSync as readdirSync21, statSync as statSync12, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "node:fs";
9963
- import { join as join69 } from "node:path";
10148
+ import { mkdirSync as mkdirSync16, readdirSync as readdirSync21, statSync as statSync14, unlinkSync as unlinkSync2, writeFileSync as writeFileSync11 } from "node:fs";
10149
+ import { join as join70 } from "node:path";
9964
10150
 
9965
10151
  // src/crash-report.ts
9966
10152
  var CRASH_MAX_STACK_LINES = 50;
@@ -10045,15 +10231,15 @@ function buildCrashReport(input) {
10045
10231
  // src/crash-report.redact.ts
10046
10232
  import { mkdtempSync as mkdtempSync3, rmSync as rmSync21, writeFileSync as writeFileSync10 } from "node:fs";
10047
10233
  import { tmpdir as tmpdir2 } from "node:os";
10048
- import { join as join68 } from "node:path";
10234
+ import { join as join69 } from "node:path";
10049
10235
  init_push_gitleaks_scan();
10050
10236
  var CRASH_SCAN_TIMEOUT_MS = 3e3;
10051
10237
  var SCAN_UNAVAILABLE_ADVISORY = "\n\n[gitleaks value-based scan unavailable; only structural redaction applied. Review before sharing this file publicly.]\n";
10052
10238
  function redactWithGitleaks(text, scan = scanFile) {
10053
10239
  let dir;
10054
10240
  try {
10055
- dir = mkdtempSync3(join68(tmpdir2(), "nomad-crash-scan-"));
10056
- const tmp = join68(dir, "crash.txt");
10241
+ dir = mkdtempSync3(join69(tmpdir2(), "nomad-crash-scan-"));
10242
+ const tmp = join69(dir, "crash.txt");
10057
10243
  writeFileSync10(tmp, text, { mode: 384 });
10058
10244
  const findings = scan(tmp, false, CRASH_SCAN_TIMEOUT_MS);
10059
10245
  if (findings === null) return text + SCAN_UNAVAILABLE_ADVISORY;
@@ -10078,7 +10264,7 @@ function listCrashFiles(dir = crashDir()) {
10078
10264
  try {
10079
10265
  return readdirSync21(dir).flatMap((name) => {
10080
10266
  try {
10081
- return [{ name, mtimeMs: statSync12(join69(dir, name)).mtimeMs }];
10267
+ return [{ name, mtimeMs: statSync14(join70(dir, name)).mtimeMs }];
10082
10268
  } catch {
10083
10269
  return [];
10084
10270
  }
@@ -10092,7 +10278,7 @@ function pruneCrashDir(dir, keep = CRASH_RETENTION_KEEP) {
10092
10278
  const targets = prunableByCount(files, keep);
10093
10279
  for (const name of targets) {
10094
10280
  try {
10095
- unlinkSync2(join69(dir, name));
10281
+ unlinkSync2(join70(dir, name));
10096
10282
  } catch {
10097
10283
  }
10098
10284
  }
@@ -10100,7 +10286,7 @@ function pruneCrashDir(dir, keep = CRASH_RETENTION_KEEP) {
10100
10286
  function writeCrashReport(text, dir = crashDir()) {
10101
10287
  mkdirSync16(dir, { recursive: true, mode: 448 });
10102
10288
  const stamp = `${nowTimestamp()}-${process.pid}-${randomBytes5(4).toString("hex")}`;
10103
- const path = join69(dir, `crash-${stamp}.txt`);
10289
+ const path = join70(dir, `crash-${stamp}.txt`);
10104
10290
  writeFileSync11(path, text, { mode: 384 });
10105
10291
  pruneCrashDir(dir);
10106
10292
  return path;
@@ -10132,18 +10318,18 @@ function handleCrash(err, argv, opts) {
10132
10318
 
10133
10319
  // src/diff.ts
10134
10320
  init_config();
10135
- import { existsSync as existsSync53 } from "node:fs";
10136
- import { join as join70 } from "node:path";
10321
+ import { existsSync as existsSync52 } from "node:fs";
10322
+ import { join as join71 } from "node:path";
10137
10323
  init_utils();
10138
10324
  init_utils_fs();
10139
10325
  init_utils_json();
10140
10326
  function cmdDiff() {
10141
10327
  try {
10142
10328
  const repo = repoHome();
10143
- if (!existsSync53(repo)) die(`repo not cloned at ${repo}`);
10329
+ if (!existsSync52(repo)) die(`repo not cloned at ${repo}`);
10144
10330
  const ts = freshBackupTs(backupBase());
10145
- const mapPath = join70(repo, "path-map.json");
10146
- const map = existsSync53(mapPath) ? readPathMap(mapPath) : { projects: {} };
10331
+ const mapPath = join71(repo, "path-map.json");
10332
+ const map = existsSync52(mapPath) ? readPathMap(mapPath) : { projects: {} };
10147
10333
  divergenceCheckExtras(ts);
10148
10334
  computePreview(ts, map, "diff");
10149
10335
  } catch (err) {
@@ -10158,8 +10344,8 @@ function cmdDiff() {
10158
10344
 
10159
10345
  // src/init.ts
10160
10346
  init_config();
10161
- import { existsSync as existsSync55, mkdirSync as mkdirSync17, writeFileSync as writeFileSync12 } from "node:fs";
10162
- import { join as join72 } from "node:path";
10347
+ import { existsSync as existsSync54, mkdirSync as mkdirSync17, writeFileSync as writeFileSync12 } from "node:fs";
10348
+ import { join as join73 } from "node:path";
10163
10349
 
10164
10350
  // src/init.gh-onboard.ts
10165
10351
  init_config();
@@ -10241,33 +10427,33 @@ init_config();
10241
10427
  init_utils();
10242
10428
  init_utils_fs();
10243
10429
  init_utils_json();
10244
- import { copyFileSync as copyFileSync2, cpSync as cpSync9, existsSync as existsSync54, rmSync as rmSync22, statSync as statSync13 } from "node:fs";
10245
- import { join as join71 } from "node:path";
10430
+ import { copyFileSync as copyFileSync2, cpSync as cpSync9, existsSync as existsSync53, rmSync as rmSync22, statSync as statSync15 } from "node:fs";
10431
+ import { join as join72 } from "node:path";
10246
10432
  function snapshotIntoShared(map) {
10247
10433
  const repo = repoHome();
10248
10434
  const claude = claudeHome();
10249
10435
  for (const name of allSharedLinks(map)) {
10250
- const src = join71(claude, name);
10251
- if (!existsSync54(src)) continue;
10252
- const dst = join71(repo, "shared", name);
10253
- if (statSync13(src).isDirectory()) {
10254
- const gk = join71(dst, ".gitkeep");
10255
- if (existsSync54(gk)) rmSync22(gk);
10436
+ const src = join72(claude, name);
10437
+ if (!existsSync53(src)) continue;
10438
+ const dst = join72(repo, "shared", name);
10439
+ if (statSync15(src).isDirectory()) {
10440
+ const gk = join72(dst, ".gitkeep");
10441
+ if (existsSync53(gk)) rmSync22(gk);
10256
10442
  cpSync9(src, dst, { recursive: true, force: false, errorOnExist: true });
10257
10443
  } else {
10258
10444
  copyFileSync2(src, dst);
10259
10445
  }
10260
10446
  log(`snapshotted shared/${name} from ${src}`);
10261
10447
  }
10262
- const userSettings = join71(claude, "settings.json");
10263
- if (existsSync54(userSettings)) {
10448
+ const userSettings = join72(claude, "settings.json");
10449
+ if (existsSync53(userSettings)) {
10264
10450
  let parsed;
10265
10451
  try {
10266
10452
  parsed = readJson(userSettings);
10267
10453
  } catch (err) {
10268
10454
  return die(`malformed ${userSettings}: ${err.message}`);
10269
10455
  }
10270
- const hostFile = join71(repo, "hosts", `${HOST}.json`);
10456
+ const hostFile = join72(repo, "hosts", `${HOST}.json`);
10271
10457
  writeJsonAtomic(hostFile, parsed);
10272
10458
  log(`snapshotted hosts/${HOST}.json from ${userSettings}`);
10273
10459
  }
@@ -10281,14 +10467,14 @@ var GITATTRIBUTES = "# nomad: sync content is byte-managed, disable all line-end
10281
10467
  var SHARED_KEEP_DIRS = ["agents", "skills", "commands", "rules", "hooks"];
10282
10468
  function preflightConflict(repoHome2) {
10283
10469
  const candidates = [
10284
- join72(repoHome2, "shared", "settings.base.json"),
10285
- join72(repoHome2, "shared", "CLAUDE.md"),
10286
- join72(repoHome2, "path-map.json"),
10287
- join72(repoHome2, "hosts"),
10288
- join72(repoHome2, "shared")
10470
+ join73(repoHome2, "shared", "settings.base.json"),
10471
+ join73(repoHome2, "shared", "CLAUDE.md"),
10472
+ join73(repoHome2, "path-map.json"),
10473
+ join73(repoHome2, "hosts"),
10474
+ join73(repoHome2, "shared")
10289
10475
  ];
10290
10476
  for (const c of candidates) {
10291
- if (existsSync55(c)) return c;
10477
+ if (existsSync54(c)) return c;
10292
10478
  }
10293
10479
  return null;
10294
10480
  }
@@ -10306,27 +10492,27 @@ function cmdInit(opts = {}) {
10306
10492
  die(`already initialized; refusing to clobber ${conflict}`);
10307
10493
  }
10308
10494
  ensureOriginRepo(opts.repoName ?? DEFAULT_REPO_NAME, opts.run);
10309
- mkdirSync17(join72(repo, "shared"), { recursive: true });
10310
- mkdirSync17(join72(repo, "hosts"), { recursive: true });
10495
+ mkdirSync17(join73(repo, "shared"), { recursive: true });
10496
+ mkdirSync17(join73(repo, "hosts"), { recursive: true });
10311
10497
  for (const name of SHARED_KEEP_DIRS) {
10312
- mkdirSync17(join72(repo, "shared", name), { recursive: true });
10498
+ mkdirSync17(join73(repo, "shared", name), { recursive: true });
10313
10499
  }
10314
- const userClaudeMd = join72(claude, "CLAUDE.md");
10315
- if (!snapshot || !existsSync55(userClaudeMd)) {
10316
- writeFileSync12(join72(repo, "shared", "CLAUDE.md"), SHARED_CLAUDE_MD);
10500
+ const userClaudeMd = join73(claude, "CLAUDE.md");
10501
+ if (!snapshot || !existsSync54(userClaudeMd)) {
10502
+ writeFileSync12(join73(repo, "shared", "CLAUDE.md"), SHARED_CLAUDE_MD);
10317
10503
  item("created shared/CLAUDE.md");
10318
10504
  }
10319
10505
  for (const name of SHARED_KEEP_DIRS) {
10320
- writeFileSync12(join72(repo, "shared", name, ".gitkeep"), "");
10506
+ writeFileSync12(join73(repo, "shared", name, ".gitkeep"), "");
10321
10507
  item(`created shared/${name}/.gitkeep`);
10322
10508
  }
10323
- writeFileSync12(join72(repo, "hosts", ".gitkeep"), "");
10509
+ writeFileSync12(join73(repo, "hosts", ".gitkeep"), "");
10324
10510
  item("created hosts/.gitkeep");
10325
- writeJsonAtomic(join72(repo, "shared", "settings.base.json"), {});
10511
+ writeJsonAtomic(join73(repo, "shared", "settings.base.json"), {});
10326
10512
  item("created shared/settings.base.json");
10327
- writeJsonAtomic(join72(repo, "path-map.json"), { projects: {} });
10513
+ writeJsonAtomic(join73(repo, "path-map.json"), { projects: {} });
10328
10514
  item("created path-map.json");
10329
- writeFileSync12(join72(repo, ".gitattributes"), GITATTRIBUTES);
10515
+ writeFileSync12(join73(repo, ".gitattributes"), GITATTRIBUTES);
10330
10516
  item("created .gitattributes");
10331
10517
  if (snapshot) {
10332
10518
  snapshotIntoShared({ projects: {} });
@@ -10392,21 +10578,21 @@ function maybeDisableRepoActions(repoHome2, run) {
10392
10578
  // src/init.prompt.ts
10393
10579
  init_config();
10394
10580
  init_utils();
10395
- import { existsSync as existsSync56, readdirSync as readdirSync22, statSync as statSync14 } from "node:fs";
10396
- import { join as join73 } from "node:path";
10581
+ import { existsSync as existsSync55, readdirSync as readdirSync22, statSync as statSync16 } from "node:fs";
10582
+ import { join as join74 } from "node:path";
10397
10583
  import { createInterface as createInterface3 } from "node:readline/promises";
10398
10584
  function nonEmptyExists(path) {
10399
- if (!existsSync56(path)) return false;
10585
+ if (!existsSync55(path)) return false;
10400
10586
  try {
10401
- if (statSync14(path).isDirectory()) return readdirSync22(path).length > 0;
10587
+ if (statSync16(path).isDirectory()) return readdirSync22(path).length > 0;
10402
10588
  return true;
10403
10589
  } catch {
10404
10590
  return false;
10405
10591
  }
10406
10592
  }
10407
10593
  function hasExistingClaudeConfig(claudeHome2) {
10408
- if (existsSync56(join73(claudeHome2, "settings.json"))) return true;
10409
- return SHARED_LINKS.some((name) => nonEmptyExists(join73(claudeHome2, name)));
10594
+ if (existsSync55(join74(claudeHome2, "settings.json"))) return true;
10595
+ return SHARED_LINKS.some((name) => nonEmptyExists(join74(claudeHome2, name)));
10410
10596
  }
10411
10597
  async function confirmSnapshotDefault(claudeHome2) {
10412
10598
  if (process.stdin.isTTY !== true || process.stdout.isTTY !== true) {
@@ -10713,7 +10899,7 @@ function parseSyncArgs(argv) {
10713
10899
  // package.json
10714
10900
  var package_default = {
10715
10901
  name: "claude-nomad",
10716
- version: "0.67.1",
10902
+ version: "0.67.2",
10717
10903
  type: "module",
10718
10904
  description: "Sync Claude Code config (~/.claude/) across machines via a private Git repo, with path remapping and per-host settings overrides.",
10719
10905
  keywords: [
@@ -10786,10 +10972,11 @@ var package_default = {
10786
10972
  "@commitlint/cli": "^21.0.1",
10787
10973
  "@commitlint/config-conventional": "^21.0.1",
10788
10974
  "@eslint/js": "^10.0.1",
10789
- "@stryker-mutator/core": "9.6.1",
10790
- "@stryker-mutator/vitest-runner": "9.6.1",
10975
+ "@stryker-mutator/core": "10.0.0",
10976
+ "@stryker-mutator/vitest-runner": "10.0.0",
10791
10977
  "@types/node": "^22.0.0",
10792
10978
  "@vitest/coverage-v8": "^4.1.6",
10979
+ "conventional-changelog-conventionalcommits": "^10.2.1",
10793
10980
  diff: "^9.0.0",
10794
10981
  esbuild: "^0.28.0",
10795
10982
  eslint: "^10.4.0",
@@ -10960,15 +11147,15 @@ var DEFAULT_HELP = [
10960
11147
  init_config();
10961
11148
  init_utils();
10962
11149
  init_utils_json();
10963
- import { existsSync as existsSync57, readFileSync as readFileSync21, readdirSync as readdirSync23 } from "node:fs";
10964
- import { join as join74 } from "node:path";
11150
+ import { existsSync as existsSync56, readFileSync as readFileSync21, readdirSync as readdirSync23 } from "node:fs";
11151
+ import { join as join75 } from "node:path";
10965
11152
  function resumeCmd(sessionId) {
10966
11153
  if (!/^[A-Za-z0-9_-]+$/.test(sessionId) || sessionId.length > 128) {
10967
11154
  fail(`invalid session id: ${sessionId}`);
10968
11155
  process.exit(1);
10969
11156
  }
10970
- const projectsRoot = join74(claudeHome(), "projects");
10971
- if (!existsSync57(projectsRoot)) {
11157
+ const projectsRoot = join75(claudeHome(), "projects");
11158
+ if (!existsSync56(projectsRoot)) {
10972
11159
  fail(`${projectsRoot} does not exist`);
10973
11160
  process.exit(1);
10974
11161
  }
@@ -10982,8 +11169,8 @@ function resumeCmd(sessionId) {
10982
11169
  fail(`no cwd field found in ${jsonlPath}`);
10983
11170
  process.exit(1);
10984
11171
  }
10985
- const mapPath = join74(repoHome(), "path-map.json");
10986
- if (!existsSync57(mapPath)) {
11172
+ const mapPath = join75(repoHome(), "path-map.json");
11173
+ if (!existsSync56(mapPath)) {
10987
11174
  fail("path-map.json missing");
10988
11175
  process.exit(1);
10989
11176
  }
@@ -11006,8 +11193,8 @@ function resumeCmd(sessionId) {
11006
11193
  }
11007
11194
  function findTranscriptPath(projectsRoot, sessionId) {
11008
11195
  for (const dir of readdirSync23(projectsRoot)) {
11009
- const candidate = join74(projectsRoot, dir, `${sessionId}.jsonl`);
11010
- if (existsSync57(candidate)) return candidate;
11196
+ const candidate = join75(projectsRoot, dir, `${sessionId}.jsonl`);
11197
+ if (existsSync56(candidate)) return candidate;
11011
11198
  }
11012
11199
  return null;
11013
11200
  }