switchroom 0.19.7 → 0.19.9

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.
@@ -2120,7 +2120,7 @@ var init_esm = __esm(() => {
2120
2120
  });
2121
2121
 
2122
2122
  // src/build-info.ts
2123
- var VERSION = "0.19.7", COMMIT_SHA = "2ddec4ae";
2123
+ var VERSION = "0.19.9", COMMIT_SHA = "9d791e63";
2124
2124
 
2125
2125
  // src/cli/resolve-version.ts
2126
2126
  import { existsSync, readFileSync } from "node:fs";
@@ -23861,7 +23861,8 @@ function getBuiltinDefaultSkillEntries() {
23861
23861
  "switchroom-health",
23862
23862
  "switchroom-runtime",
23863
23863
  "mental-model-curator",
23864
- "dev-protocol"
23864
+ "dev-protocol",
23865
+ "telegram-formatting"
23865
23866
  ];
23866
23867
  return [
23867
23868
  ...anthropic.map((key) => ({ key, optOutKey: key, source: "anthropic" })),
@@ -23938,7 +23939,7 @@ function bindingsForAgent(agentName, mw, microsoftAccounts) {
23938
23939
  // src/agents/reconcile-default-skills.ts
23939
23940
  import { existsSync as existsSync8, lstatSync as lstatSync2, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readlinkSync as readlinkSync3, rmSync as rmSync2, symlinkSync } from "node:fs";
23940
23941
  import { homedir as homedir3 } from "node:os";
23941
- import { join as join6, resolve as resolve5 } from "node:path";
23942
+ import { dirname as dirname2, isAbsolute, join as join6, relative, resolve as resolve5 } from "node:path";
23942
23943
  function warnMissingPoolDir(poolDir) {
23943
23944
  if (warnedMissingPool.has(poolDir))
23944
23945
  return;
@@ -23946,6 +23947,14 @@ function warnMissingPoolDir(poolDir) {
23946
23947
  process.stderr.write(`switchroom: bundled skills pool dir not found at ${poolDir} \u2014 run \`switchroom update\` to install it.
23947
23948
  `);
23948
23949
  }
23950
+ function warnMissingBuiltinDefault(poolDir, key) {
23951
+ const marker = `${poolDir} ${key}`;
23952
+ if (warnedMissingDefault.has(marker))
23953
+ return;
23954
+ warnedMissingDefault.add(marker);
23955
+ process.stderr.write(`switchroom: ERROR \u2014 builtin default skill "${key}" is missing from the bundled pool ` + `(${poolDir}). It ships in the CLI package but was not synced. ` + `Re-run \`switchroom update\` to repair the pool; if it persists this is a packaging bug.
23956
+ `);
23957
+ }
23949
23958
  function getBundledSkillsPoolDir() {
23950
23959
  return resolve5(homedir3(), ".switchroom/skills/_bundled");
23951
23960
  }
@@ -23960,6 +23969,27 @@ function isOwnedStaleLink(target, poolDir) {
23960
23969
  return true;
23961
23970
  return false;
23962
23971
  }
23972
+ function absoluteLinkTarget(linkPath, storedTarget) {
23973
+ return isAbsolute(storedTarget) ? storedTarget : resolve5(dirname2(linkPath), storedTarget);
23974
+ }
23975
+ function linkTargetFor(dest, src) {
23976
+ return relative(dirname2(dest), src);
23977
+ }
23978
+ function isOwnedBundledLink(dest, poolDir) {
23979
+ let stored = null;
23980
+ try {
23981
+ if (!lstatSync2(dest).isSymbolicLink())
23982
+ return false;
23983
+ stored = readlinkSync3(dest);
23984
+ } catch {
23985
+ return false;
23986
+ }
23987
+ if (!stored)
23988
+ return false;
23989
+ const resolved = isAbsolute(stored) ? stored : resolve5(dirname2(dest), stored);
23990
+ const poolPrefix = poolDir.endsWith("/") ? poolDir : poolDir + "/";
23991
+ return resolved === poolDir || resolved.startsWith(poolPrefix);
23992
+ }
23963
23993
  function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuiltinDefaultSkillEntries(), poolDir = getBundledSkillsPoolDir()) {
23964
23994
  const name = agentDir.split("/").pop() ?? agentDir;
23965
23995
  const result = {
@@ -23968,6 +23998,8 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
23968
23998
  alreadyPresent: [],
23969
23999
  optedOut: [],
23970
24000
  conflicts: [],
24001
+ missingFromPool: [],
24002
+ pruned: [],
23971
24003
  changed: false
23972
24004
  };
23973
24005
  const claudeDir = join6(agentDir, ".claude");
@@ -23981,15 +24013,32 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
23981
24013
  return result;
23982
24014
  }
23983
24015
  for (const entry of defaults) {
24016
+ const dest = join6(targetDir, entry.key);
23984
24017
  if (optOuts[entry.optOutKey] === false) {
23985
24018
  result.optedOut.push(entry.key);
24019
+ if (isOwnedBundledLink(dest, poolDir)) {
24020
+ try {
24021
+ rmSync2(dest, { force: true });
24022
+ result.pruned.push(entry.key);
24023
+ result.changed = true;
24024
+ } catch {}
24025
+ }
23986
24026
  continue;
23987
24027
  }
23988
24028
  const src = join6(poolDir, entry.key);
23989
24029
  if (!existsSync8(src)) {
24030
+ result.missingFromPool.push(entry.key);
24031
+ warnMissingBuiltinDefault(poolDir, entry.key);
24032
+ if (isOwnedBundledLink(dest, poolDir)) {
24033
+ try {
24034
+ rmSync2(dest, { force: true });
24035
+ result.pruned.push(entry.key);
24036
+ result.changed = true;
24037
+ } catch {}
24038
+ }
23990
24039
  continue;
23991
24040
  }
23992
- const dest = join6(targetDir, entry.key);
24041
+ const relTarget = linkTargetFor(dest, src);
23993
24042
  let existing;
23994
24043
  try {
23995
24044
  existing = lstatSync2(dest);
@@ -24002,11 +24051,12 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
24002
24051
  try {
24003
24052
  currentTarget = readlinkSync3(dest);
24004
24053
  } catch {}
24005
- if (currentTarget === src) {
24054
+ if (currentTarget === relTarget) {
24006
24055
  result.alreadyPresent.push(entry.key);
24007
24056
  continue;
24008
24057
  }
24009
- if (currentTarget && isOwnedStaleLink(currentTarget, poolDir)) {
24058
+ const resolvedTarget = currentTarget ? absoluteLinkTarget(dest, currentTarget) : null;
24059
+ if (resolvedTarget && isOwnedStaleLink(resolvedTarget, poolDir)) {
24010
24060
  try {
24011
24061
  rmSync2(dest, { force: true });
24012
24062
  } catch {}
@@ -24020,7 +24070,7 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
24020
24070
  }
24021
24071
  }
24022
24072
  try {
24023
- symlinkSync(src, dest);
24073
+ symlinkSync(relTarget, dest);
24024
24074
  result.added.push(entry.key);
24025
24075
  result.changed = true;
24026
24076
  } catch (err) {
@@ -24029,10 +24079,11 @@ function reconcileAgentDefaultSkills(agentDir, optOuts = {}, defaults = getBuilt
24029
24079
  }
24030
24080
  return result;
24031
24081
  }
24032
- var warnedMissingPool;
24082
+ var warnedMissingPool, warnedMissingDefault;
24033
24083
  var init_reconcile_default_skills = __esm(() => {
24034
24084
  init_scaffold_integration();
24035
24085
  warnedMissingPool = new Set;
24086
+ warnedMissingDefault = new Set;
24036
24087
  });
24037
24088
 
24038
24089
  // src/agents/sub-agent-telegram-prompt.ts
@@ -24088,7 +24139,7 @@ import {
24088
24139
  copyFileSync as copyFileSync2,
24089
24140
  unlinkSync
24090
24141
  } from "node:fs";
24091
- import { basename as basename2, dirname as dirname2, resolve as resolve6 } from "node:path";
24142
+ import { basename as basename2, dirname as dirname3, resolve as resolve6 } from "node:path";
24092
24143
  function defaultStatePath() {
24093
24144
  return resolveStatePath("topics.json");
24094
24145
  }
@@ -24115,7 +24166,7 @@ function loadTopicState(statePath) {
24115
24166
  }
24116
24167
  function saveTopicState(state, statePath) {
24117
24168
  const path = statePath ?? defaultStatePath();
24118
- const dir = dirname2(path);
24169
+ const dir = dirname3(path);
24119
24170
  if (!existsSync9(dir)) {
24120
24171
  mkdirSync4(dir, { recursive: true });
24121
24172
  }
@@ -24387,7 +24438,7 @@ import {
24387
24438
  lstatSync as lstatSync3,
24388
24439
  realpathSync as realpathSync2
24389
24440
  } from "node:fs";
24390
- import { dirname as dirname3, basename as basename3, resolve as resolve7 } from "node:path";
24441
+ import { dirname as dirname4, basename as basename3, resolve as resolve7 } from "node:path";
24391
24442
  function atomicWriteFileSync2(path, data, mode) {
24392
24443
  let effectivePath = path;
24393
24444
  try {
@@ -24395,7 +24446,7 @@ function atomicWriteFileSync2(path, data, mode) {
24395
24446
  effectivePath = realpathSync2(path);
24396
24447
  }
24397
24448
  } catch {}
24398
- const dir = dirname3(resolve7(effectivePath));
24449
+ const dir = dirname4(resolve7(effectivePath));
24399
24450
  const tmp = resolve7(dir, `.${basename3(effectivePath)}.${process.pid}.${Date.now()}.tmp`);
24400
24451
  try {
24401
24452
  const fd = openSync4(tmp, "wx", mode);
@@ -24532,7 +24583,7 @@ function createVault(passphrase, vaultPath) {
24532
24583
  if (existsSync11(vaultPath)) {
24533
24584
  throw new VaultError(`Vault file already exists: ${vaultPath}`);
24534
24585
  }
24535
- const dir = dirname3(vaultPath);
24586
+ const dir = dirname4(vaultPath);
24536
24587
  if (!existsSync11(dir)) {
24537
24588
  mkdirSync5(dir, { recursive: true, mode: 448 });
24538
24589
  }
@@ -26140,7 +26191,7 @@ import {
26140
26191
  } from "node:fs";
26141
26192
  import { homedir as homedir5 } from "node:os";
26142
26193
  import { execSync, execFileSync as execFileSync6 } from "node:child_process";
26143
- import { join as join11, resolve as resolve11 } from "node:path";
26194
+ import { dirname as dirname5, isAbsolute as isAbsolute2, join as join11, relative as relative2, resolve as resolve11 } from "node:path";
26144
26195
  import { createHash as createHash3 } from "node:crypto";
26145
26196
  function prependReplyDiscipline(rendered, context) {
26146
26197
  const replyDiscipline = renderReplyDisciplineFragment(context);
@@ -26526,7 +26577,8 @@ function migrateLegacySkillsDir(agentDir, skillsPool) {
26526
26577
  } catch {
26527
26578
  continue;
26528
26579
  }
26529
- if (target && target.startsWith(skillsPool)) {
26580
+ const resolved = target ? isAbsolute2(target) ? target : resolve11(dirname5(entryPath), target) : null;
26581
+ if (resolved && resolved.startsWith(skillsPool)) {
26530
26582
  try {
26531
26583
  rmSync4(entryPath, { force: true });
26532
26584
  } catch {}
@@ -26549,6 +26601,7 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
26549
26601
  console.warn(` WARNING: skill "${name}" not found in pool (${skillsPool}) \u2014 skipping`);
26550
26602
  continue;
26551
26603
  }
26604
+ const relTarget = relative2(dirname5(dest), src);
26552
26605
  let linkStat;
26553
26606
  try {
26554
26607
  linkStat = lstatSync4(dest);
@@ -26561,7 +26614,11 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
26561
26614
  try {
26562
26615
  target = readlinkSync4(dest);
26563
26616
  } catch {}
26564
- if (target && target.startsWith(skillsPool)) {
26617
+ if (target === relTarget) {
26618
+ continue;
26619
+ }
26620
+ const resolved = target ? isAbsolute2(target) ? target : resolve11(dirname5(dest), target) : null;
26621
+ if (resolved && resolved.startsWith(skillsPool)) {
26565
26622
  try {
26566
26623
  rmSync4(dest, { force: true });
26567
26624
  } catch {}
@@ -26573,7 +26630,7 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
26573
26630
  }
26574
26631
  }
26575
26632
  try {
26576
- symlinkSync2(src, dest);
26633
+ symlinkSync2(relTarget, dest);
26577
26634
  } catch (err) {
26578
26635
  console.warn(` WARNING: failed to symlink skill "${name}": ${err.message}`);
26579
26636
  }
@@ -26589,10 +26646,11 @@ function syncGlobalSkills(agentDir, declared, skillsDirOverride) {
26589
26646
  } catch {
26590
26647
  continue;
26591
26648
  }
26592
- if (linkTarget && linkTarget.includes("/.switchroom/skills/_bundled/")) {
26649
+ const resolved = linkTarget ? isAbsolute2(linkTarget) ? linkTarget : resolve11(dirname5(entryPath), linkTarget) : null;
26650
+ if (resolved && resolved.includes("/.switchroom/skills/_bundled/")) {
26593
26651
  continue;
26594
26652
  }
26595
- if (linkTarget && linkTarget.startsWith(skillsPool)) {
26653
+ if (resolved && resolved.startsWith(skillsPool)) {
26596
26654
  rmSync4(entryPath, { force: true });
26597
26655
  }
26598
26656
  }
@@ -26645,7 +26703,10 @@ function installSwitchroomSkills(agentDir, opts = {}) {
26645
26703
  try {
26646
26704
  currentTarget = readlinkSync4(dest);
26647
26705
  } catch {}
26648
- if (currentTarget !== join11(builtinSkillsDir, name))
26706
+ if (!currentTarget)
26707
+ continue;
26708
+ const resolvedTarget = isAbsolute2(currentTarget) ? currentTarget : resolve11(dirname5(dest), currentTarget);
26709
+ if (resolvedTarget !== join11(builtinSkillsDir, name))
26649
26710
  continue;
26650
26711
  try {
26651
26712
  rmSync4(dest, { force: true });
@@ -26656,6 +26717,7 @@ function installSwitchroomSkills(agentDir, opts = {}) {
26656
26717
  for (const name of switchroomSkillNames) {
26657
26718
  const src = join11(builtinSkillsDir, name);
26658
26719
  const dest = join11(targetDir, name);
26720
+ const relTarget = relative2(dirname5(dest), src);
26659
26721
  let existing;
26660
26722
  try {
26661
26723
  existing = lstatSync4(dest);
@@ -26668,7 +26730,7 @@ function installSwitchroomSkills(agentDir, opts = {}) {
26668
26730
  try {
26669
26731
  currentTarget = readlinkSync4(dest);
26670
26732
  } catch {}
26671
- if (currentTarget === src)
26733
+ if (currentTarget === relTarget)
26672
26734
  continue;
26673
26735
  try {
26674
26736
  rmSync4(dest, { force: true });
@@ -26678,7 +26740,7 @@ function installSwitchroomSkills(agentDir, opts = {}) {
26678
26740
  }
26679
26741
  }
26680
26742
  try {
26681
- symlinkSync2(src, dest);
26743
+ symlinkSync2(relTarget, dest);
26682
26744
  } catch (err) {
26683
26745
  console.warn(` WARNING: failed to symlink switchroom skill "${name}": ${err.message}`);
26684
26746
  }
@@ -27380,6 +27442,24 @@ function resolveWebkiteMcpEntry(_agentName, agentConfig, _switchroomConfig) {
27380
27442
  }
27381
27443
  };
27382
27444
  }
27445
+ function computeDesiredPermissionAllow(agentConfig, hindsightEnabled) {
27446
+ const tools = agentConfig.tools ?? { allow: [], deny: [] };
27447
+ const rawAllow = tools.allow ?? [];
27448
+ const hasAllWildcard = rawAllow.includes("all");
27449
+ const baseAllow = hasAllWildcard ? [...ALL_BUILTIN_TOOLS, ...rawAllow.filter((t) => t !== "all")] : rawAllow.filter((t) => t !== "all");
27450
+ const dangerousMode = agentConfig.dangerous_mode === true;
27451
+ const hadExplicitAllow = rawAllow.length > 0;
27452
+ const readOnlyDefaults = !dangerousMode && !hadExplicitAllow ? DEFAULT_READ_ONLY_PREAPPROVED_TOOLS : [];
27453
+ return dedupe2([
27454
+ ...baseAllow,
27455
+ ...readOnlyDefaults,
27456
+ ...usesSwitchroomTelegramPlugin(agentConfig) ? SWITCHROOM_TELEGRAM_MCP_TOOLS : [],
27457
+ ...hindsightEnabled ? HINDSIGHT_MCP_TOOLS : [],
27458
+ ...AGENT_CONFIG_MCP_TOOLS,
27459
+ ...HOSTD_MCP_TOOLS,
27460
+ ...agentConfig.mcp_servers?.["webkite"] === false ? [] : WEBKITE_MCP_TOOLS
27461
+ ]);
27462
+ }
27383
27463
  function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchroomConfig, userIdOverride, switchroomConfigPath) {
27384
27464
  const agentConfig = resolveAgentConfig(switchroomConfig?.defaults, switchroomConfig?.profiles, agentConfigRaw);
27385
27465
  const agentDir = resolve11(agentsDir, name);
@@ -27402,20 +27482,8 @@ function scaffoldAgent(name, agentConfigRaw, agentsDir, telegramConfig, switchro
27402
27482
  const tools = agentConfig.tools ?? { allow: [], deny: [] };
27403
27483
  const rawAllow = tools.allow ?? [];
27404
27484
  const hasAllWildcard = rawAllow.includes("all");
27405
- const baseAllow = hasAllWildcard ? [...ALL_BUILTIN_TOOLS, ...rawAllow.filter((t) => t !== "all")] : rawAllow.filter((t) => t !== "all");
27406
- const dangerousMode = agentConfig.dangerous_mode === true;
27407
- const hadExplicitAllow = rawAllow.length > 0;
27408
- const readOnlyDefaults = !dangerousMode && !hadExplicitAllow ? DEFAULT_READ_ONLY_PREAPPROVED_TOOLS : [];
27409
27485
  const hindsightEnabled = isHindsightEnabled(switchroomConfig);
27410
- const permissionAllow = dedupe2([
27411
- ...baseAllow,
27412
- ...readOnlyDefaults,
27413
- ...usesSwitchroomTelegramPlugin(agentConfig) ? SWITCHROOM_TELEGRAM_MCP_TOOLS : [],
27414
- ...hindsightEnabled ? HINDSIGHT_MCP_TOOLS : [],
27415
- ...AGENT_CONFIG_MCP_TOOLS,
27416
- ...HOSTD_MCP_TOOLS,
27417
- ...agentConfig.mcp_servers?.["webkite"] === false ? [] : WEBKITE_MCP_TOOLS
27418
- ]);
27486
+ const permissionAllow = computeDesiredPermissionAllow(agentConfig, hindsightEnabled);
27419
27487
  const hindsightAutoRecallEnabled = hindsightEnabled && agentConfig.memory?.auto_recall !== false;
27420
27488
  const hindsightBankId = agentConfig.memory?.collection ?? name;
27421
27489
  const hindsightApiBaseUrl = switchroomConfig?.memory?.config?.url ? switchroomConfig.memory.config.url.replace(/\/mcp\/?$/, "").replace(/\/$/, "") : HINDSIGHT_DEFAULT_API_BASE_URL;
@@ -28331,23 +28399,11 @@ function reconcileAgentInner(name, agentConfigRaw, agentsDir, telegramConfig, sw
28331
28399
  const tools = agentConfig.tools ?? { allow: [], deny: [] };
28332
28400
  const rawAllow = tools.allow ?? [];
28333
28401
  const hasAllWildcard = rawAllow.includes("all");
28334
- const baseAllow = hasAllWildcard ? [...ALL_BUILTIN_TOOLS, ...rawAllow.filter((t) => t !== "all")] : rawAllow.filter((t) => t !== "all");
28335
- const reconcileDangerousMode = agentConfig.dangerous_mode === true;
28336
- const reconcileHadExplicitAllow = rawAllow.length > 0;
28337
- const reconcileReadOnlyDefaults = !reconcileDangerousMode && !reconcileHadExplicitAllow ? DEFAULT_READ_ONLY_PREAPPROVED_TOOLS : [];
28338
28402
  const hindsightEnabled = isHindsightEnabled(switchroomConfig);
28403
+ const desiredAllow = computeDesiredPermissionAllow(agentConfig, hindsightEnabled);
28339
28404
  if (Array.isArray(tools.allow)) {
28340
28405
  tools.allow = tools.allow.filter((p) => !LEGACY_SWITCHROOM_MCP_TOKENS.includes(p) && !LEGACY_HOSTD_BLANKET_TOKENS.includes(p));
28341
28406
  }
28342
- const desiredAllow = dedupe2([
28343
- ...baseAllow,
28344
- ...reconcileReadOnlyDefaults,
28345
- ...usesSwitchroomTelegramPlugin(agentConfig) ? SWITCHROOM_TELEGRAM_MCP_TOOLS : [],
28346
- ...hindsightEnabled ? HINDSIGHT_MCP_TOOLS : [],
28347
- ...AGENT_CONFIG_MCP_TOOLS,
28348
- ...HOSTD_MCP_TOOLS,
28349
- ...agentConfig.mcp_servers?.["webkite"] === false ? [] : WEBKITE_MCP_TOOLS
28350
- ]);
28351
28407
  const desiredDeny = dedupe2([
28352
28408
  ...tools.deny ?? [],
28353
28409
  ...webkiteDenyForAgent(agentConfig),
@@ -29440,6 +29496,11 @@ right answer at all. Structure exists for the reader, not the writer: a two-item
29440
29496
  bullet list is worse than a sentence, a heading on a three-line reply is noise. When
29441
29497
  in doubt, shorter and plainer wins.
29442
29498
 
29499
+ Full palette when a rich or long message earns it \u2014 expandable blockquotes, spoilers,
29500
+ highlight, code-fence language hints, tables, escaping and chunking rules: load the
29501
+ \`telegram-formatting\` skill. Reach for it only when you're actually composing that
29502
+ message, never for everyday replies.
29503
+
29443
29504
  Every turn that answers a user message ends with a user-visible \`reply\`
29444
29505
  \u2014 Telegram is all the user sees; your terminal output
29445
29506
  never reaches them.`, TELEGRAM_ENV_PLACEHOLDER = `# Set your bot token: TELEGRAM_BOT_TOKEN=your-token-here
@@ -29600,7 +29661,7 @@ var init_scaffold = __esm(() => {
29600
29661
 
29601
29662
  // src/setup/host-capabilities.ts
29602
29663
  import { existsSync as existsSync17, mkdirSync as mkdirSync11, readFileSync as readFileSync14, writeFileSync as writeFileSync5 } from "node:fs";
29603
- import { dirname as dirname4 } from "node:path";
29664
+ import { dirname as dirname6 } from "node:path";
29604
29665
  function hostCapabilitiesPath() {
29605
29666
  return resolveStatePath("host-capabilities.json");
29606
29667
  }
@@ -29615,7 +29676,7 @@ function saveVoiceCapability(caps, now = () => new Date) {
29615
29676
  }
29616
29677
  };
29617
29678
  const path = hostCapabilitiesPath();
29618
- mkdirSync11(dirname4(path), { recursive: true });
29679
+ mkdirSync11(dirname6(path), { recursive: true });
29619
29680
  writeFileSync5(path, JSON.stringify(doc, null, 2) + `
29620
29681
  `, {
29621
29682
  encoding: "utf-8",
@@ -29722,11 +29783,11 @@ var init_grants_db_path = __esm(() => {
29722
29783
 
29723
29784
  // src/agents/compose.ts
29724
29785
  import { existsSync as existsSync19, mkdirSync as mkdirSync13, readFileSync as readFileSync15, lstatSync as lstatSync5, readlinkSync as readlinkSync5, chmodSync as chmodSync4 } from "node:fs";
29725
- import { join as join13, isAbsolute, dirname as dirname6, resolve as resolve13 } from "node:path";
29786
+ import { join as join13, isAbsolute as isAbsolute3, dirname as dirname8, resolve as resolve13 } from "node:path";
29726
29787
  function assertPlausibleHostHome(homePrefix) {
29727
29788
  if (homePrefix === "${HOME}")
29728
29789
  return;
29729
- const bad = !isAbsolute(homePrefix) || CONTAINER_ROOT_PREFIXES.some((p) => homePrefix === p || homePrefix.startsWith(p + "/"));
29790
+ const bad = !isAbsolute3(homePrefix) || CONTAINER_ROOT_PREFIXES.some((p) => homePrefix === p || homePrefix.startsWith(p + "/"));
29730
29791
  if (!bad)
29731
29792
  return;
29732
29793
  throw new Error(`compose: refusing to generate \u2014 the host-home prefix resolved to "${homePrefix}", ` + `which is not a real host path (it looks like an in-container root). Emitting it as a ` + `bind-mount source would make docker auto-create empty dirs on the host and crash the ` + `fleet (start.sh missing \u2192 exec 127; broker EISDIR / SQLite "unable to open").
@@ -29970,8 +30031,8 @@ function conditionalMountPresent(probePath, hostHome, probeHome) {
29970
30031
  if (!lstatSync5(probePath).isSymbolicLink())
29971
30032
  return false;
29972
30033
  let target = readlinkSync5(probePath);
29973
- if (!isAbsolute(target))
29974
- target = resolve13(dirname6(probePath), target);
30034
+ if (!isAbsolute3(target))
30035
+ target = resolve13(dirname8(probePath), target);
29975
30036
  if (hostHome && probeHome && hostHome !== probeHome) {
29976
30037
  if (target.startsWith(hostHome + "/")) {
29977
30038
  return true;
@@ -30020,7 +30081,7 @@ function generateCompose(opts) {
30020
30081
  const lines = [];
30021
30082
  lines.push("# generated by switchroom \u2014 do not edit by hand.");
30022
30083
  lines.push("# Manual edits will be overwritten on the next `switchroom agent add`");
30023
- lines.push("# (or future `switchroom reconcile`). To customise an agent, edit");
30084
+ lines.push("# or `switchroom apply`. To customise an agent, edit");
30024
30085
  lines.push("# switchroom.yaml and re-run the regenerating command.");
30025
30086
  lines.push("");
30026
30087
  lines.push(`# image tag: ${imageTag}`);
@@ -30692,7 +30753,7 @@ var init_operator_uid = () => {};
30692
30753
  import { chownSync as chownSync2 } from "node:fs";
30693
30754
  import { mkdir, readFile, writeFile, rename, copyFile } from "node:fs/promises";
30694
30755
  import { homedir as homedir7 } from "node:os";
30695
- import { basename as basename4, dirname as dirname7, join as join15 } from "node:path";
30756
+ import { basename as basename4, dirname as dirname9, join as join15 } from "node:path";
30696
30757
  function agentHadLiteLLMRouting(composeContent, agentName) {
30697
30758
  const lines = composeContent.split(`
30698
30759
  `);
@@ -30833,7 +30894,7 @@ async function computeComposeContent(opts) {
30833
30894
  async function writeComposeFile(opts) {
30834
30895
  const { content, imageTag, previous, previousImageTag } = await computeComposeContent(opts);
30835
30896
  const operatorUid = resolveOperatorUid();
30836
- await mkdir(dirname7(opts.composePath), { recursive: true });
30897
+ await mkdir(dirname9(opts.composePath), { recursive: true });
30837
30898
  if (previous !== null) {
30838
30899
  try {
30839
30900
  await copyFile(opts.composePath, opts.composePath + ".bak");
@@ -30902,9 +30963,9 @@ var init_tmux = __esm(() => {
30902
30963
 
30903
30964
  // src/agents/compose-env.ts
30904
30965
  import { existsSync as existsSync21 } from "node:fs";
30905
- import { dirname as dirname8 } from "node:path";
30966
+ import { dirname as dirname10 } from "node:path";
30906
30967
  function composeEnvPath(composePath) {
30907
- return dirname8(composePath) + "/.env";
30968
+ return dirname10(composePath) + "/.env";
30908
30969
  }
30909
30970
  function composeEnvFileArgs(composePath) {
30910
30971
  const envPath = composeEnvPath(composePath);
@@ -35572,7 +35633,7 @@ import {
35572
35633
  unlinkSync as unlinkSync7
35573
35634
  } from "node:fs";
35574
35635
  import { createHash as createHash6 } from "node:crypto";
35575
- import { basename as basename5, dirname as dirname9, join as join31 } from "node:path";
35636
+ import { basename as basename5, dirname as dirname11, join as join31 } from "node:path";
35576
35637
  function vaultLayoutPaths(home2) {
35577
35638
  const switchroomRoot = join31(home2, ".switchroom");
35578
35639
  return {
@@ -35725,7 +35786,7 @@ function sha256File(path2) {
35725
35786
  return createHash6("sha256").update(data).digest("hex");
35726
35787
  }
35727
35788
  function atomicReplaceWithSymlink(target, linkTarget) {
35728
- const tmp = join31(dirname9(target), `.${basename5(target)}.symlink-tmp`);
35789
+ const tmp = join31(dirname11(target), `.${basename5(target)}.symlink-tmp`);
35729
35790
  if (existsSync39(tmp)) {
35730
35791
  try {
35731
35792
  unlinkSync7(tmp);
@@ -35779,7 +35840,7 @@ import {
35779
35840
  unlinkSync as unlinkSync8,
35780
35841
  writeSync as writeSync5
35781
35842
  } from "node:fs";
35782
- import { basename as basename6, dirname as dirname10, resolve as resolve27 } from "node:path";
35843
+ import { basename as basename6, dirname as dirname12, resolve as resolve27 } from "node:path";
35783
35844
  function readMachineId() {
35784
35845
  const vitestVal = process.env.VITEST;
35785
35846
  const isTestEnv = vitestVal !== undefined && vitestVal.length > 0;
@@ -35844,7 +35905,7 @@ function decryptAutoUnlock(blob, machineId) {
35844
35905
  }
35845
35906
  function writeAutoUnlockFile(passphrase, filePath) {
35846
35907
  const blob = encryptAutoUnlock(passphrase);
35847
- const dir = dirname10(filePath);
35908
+ const dir = dirname12(filePath);
35848
35909
  mkdirSync23(dir, { recursive: true, mode: 448 });
35849
35910
  const tmp = resolve27(dir, `.${basename6(filePath)}.${process.pid}.${Date.now()}.tmp`);
35850
35911
  try {
@@ -36951,7 +37012,7 @@ function formatForCli(entries, opts = {}) {
36951
37012
  var init_audit_reader = () => {};
36952
37013
 
36953
37014
  // node_modules/.bun/posthog-node@5.29.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
36954
- import { dirname as dirname14, posix, sep as sep2 } from "path";
37015
+ import { dirname as dirname16, posix, sep as sep2 } from "path";
36955
37016
  function createModulerModifier() {
36956
37017
  const getModuleFromFileName = createGetModuleFromFilename();
36957
37018
  return async (frames) => {
@@ -36960,7 +37021,7 @@ function createModulerModifier() {
36960
37021
  return frames;
36961
37022
  };
36962
37023
  }
36963
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname14(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
37024
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname16(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
36964
37025
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
36965
37026
  return (filename) => {
36966
37027
  if (!filename)
@@ -41576,7 +41637,7 @@ import {
41576
41637
  readFileSync as readFileSync45,
41577
41638
  writeFileSync as writeFileSync15
41578
41639
  } from "node:fs";
41579
- import { dirname as dirname15 } from "node:path";
41640
+ import { dirname as dirname17 } from "node:path";
41580
41641
  import { randomUUID as randomUUID3 } from "node:crypto";
41581
41642
  function telemetryDisabled() {
41582
41643
  const v = process.env.SWITCHROOM_TELEMETRY_DISABLED;
@@ -41598,7 +41659,7 @@ function getDistinctId() {
41598
41659
  const id = randomUUID3();
41599
41660
  cachedDistinctId = id;
41600
41661
  try {
41601
- mkdirSync27(dirname15(path5), { recursive: true });
41662
+ mkdirSync27(dirname17(path5), { recursive: true });
41602
41663
  writeFileSync15(path5, id, "utf-8");
41603
41664
  } catch {}
41604
41665
  return id;
@@ -41845,7 +41906,7 @@ import {
41845
41906
  readFileSync as readFileSync55,
41846
41907
  readdirSync as readdirSync21
41847
41908
  } from "node:fs";
41848
- import { dirname as dirname19, join as join53 } from "node:path";
41909
+ import { dirname as dirname21, join as join53 } from "node:path";
41849
41910
  import { execSync as execSync2 } from "node:child_process";
41850
41911
  function locateManifestPath() {
41851
41912
  let dir = import.meta.dirname;
@@ -41853,7 +41914,7 @@ function locateManifestPath() {
41853
41914
  const candidate = join53(dir, "dependencies.json");
41854
41915
  if (existsSync60(candidate))
41855
41916
  return candidate;
41856
- dir = dirname19(dir);
41917
+ dir = dirname21(dir);
41857
41918
  }
41858
41919
  return null;
41859
41920
  }
@@ -42707,7 +42768,7 @@ function checkAgentSocketMounts(composeYaml) {
42707
42768
  name: "agent socket-volume isolation",
42708
42769
  status: "fail",
42709
42770
  detail: `Cross-mounted socket volumes: ${violations.join("; ")}`,
42710
- fix: "Re-run `switchroom reconcile` to regenerate the compose from cascade. Hand-edits violating per-agent socket isolation are the load-bearing security invariant."
42771
+ fix: "Re-run `switchroom apply` to regenerate the compose from cascade. Hand-edits violating per-agent socket isolation are the load-bearing security invariant."
42711
42772
  };
42712
42773
  }
42713
42774
  function checkAgentCaps(config) {
@@ -42905,7 +42966,7 @@ function runDockerChecks(args) {
42905
42966
  name: "compose file present",
42906
42967
  status: "warn",
42907
42968
  detail: "Docker mode active but no docker-compose.yml found at ~/.switchroom/compose/docker-compose.yml",
42908
- fix: "Run `switchroom reconcile` to generate it."
42969
+ fix: "Run `switchroom apply` to generate it."
42909
42970
  });
42910
42971
  }
42911
42972
  out.push(...checkContainerRuntimeHealth(args.config, args.dockerPsDeps));
@@ -45927,7 +45988,7 @@ import {
45927
45988
  readdirSync as readdirSync23,
45928
45989
  statSync as statSync38
45929
45990
  } from "node:fs";
45930
- import { dirname as dirname20, join as join68, resolve as resolve39 } from "node:path";
45991
+ import { dirname as dirname22, join as join68, resolve as resolve39 } from "node:path";
45931
45992
  import { createPublicKey, createPrivateKey } from "node:crypto";
45932
45993
  function findInNvm(bin) {
45933
45994
  const nvmRoot = join68(process.env.HOME ?? "", ".nvm", "versions", "node");
@@ -47524,7 +47585,7 @@ async function checkMffAuthFlow(envPath = mffEnvPath(), timeoutMs = 8000) {
47524
47585
  detail: "skipped (MFF_API_URL not set)"
47525
47586
  };
47526
47587
  }
47527
- const credDir = dirname20(envPath);
47588
+ const credDir = dirname22(envPath);
47528
47589
  const authScript = join68(credDir, "claude-auth.py");
47529
47590
  if (!existsSync66(authScript)) {
47530
47591
  return {
@@ -48584,8 +48645,8 @@ var init_fleet_defaults = __esm(() => {
48584
48645
  });
48585
48646
 
48586
48647
  // src/agents/connection-health.ts
48587
- import { mkdirSync as mkdirSync46, writeFileSync as writeFileSync28 } from "node:fs";
48588
- import { join as join84 } from "node:path";
48648
+ import { mkdirSync as mkdirSync47, writeFileSync as writeFileSync29 } from "node:fs";
48649
+ import { join as join85 } from "node:path";
48589
48650
  async function computeAgentConnectionIssues(config, agentName, vaultAclReader) {
48590
48651
  const reqs = computeMcpSecretRequirements(config).filter((r) => r.agent === agentName);
48591
48652
  if (reqs.length === 0)
@@ -48642,10 +48703,10 @@ async function computeAgentConnectionIssues(config, agentName, vaultAclReader) {
48642
48703
  return issues;
48643
48704
  }
48644
48705
  function writeConnectionHealthFile(agentDir, health, deps) {
48645
- const dir = join84(agentDir, ".claude");
48646
- const path8 = join84(dir, CONNECTION_HEALTH_FILENAME);
48647
- (deps?.mkdir ?? ((p, o) => mkdirSync46(p, o)))(dir, { recursive: true });
48648
- (deps?.writeFile ?? ((p, d) => writeFileSync28(p, d)))(path8, JSON.stringify(health, null, 2) + `
48706
+ const dir = join85(agentDir, ".claude");
48707
+ const path8 = join85(dir, CONNECTION_HEALTH_FILENAME);
48708
+ (deps?.mkdir ?? ((p, o) => mkdirSync47(p, o)))(dir, { recursive: true });
48709
+ (deps?.writeFile ?? ((p, d) => writeFileSync29(p, d)))(path8, JSON.stringify(health, null, 2) + `
48649
48710
  `);
48650
48711
  }
48651
48712
  async function refreshAgentConnectionHealth(config, agentName, agentDir, deps) {
@@ -48666,10 +48727,10 @@ var CONNECTION_HEALTH_FILENAME = "connection-health.json";
48666
48727
  var init_connection_health = () => {};
48667
48728
 
48668
48729
  // src/cli/update-prompt-hook.ts
48669
- import { existsSync as existsSync83, readFileSync as readFileSync72, writeFileSync as writeFileSync29, chmodSync as chmodSync12, mkdirSync as mkdirSync47 } from "node:fs";
48670
- import { join as join85 } from "node:path";
48730
+ import { existsSync as existsSync84, readFileSync as readFileSync73, writeFileSync as writeFileSync30, chmodSync as chmodSync12, mkdirSync as mkdirSync48 } from "node:fs";
48731
+ import { join as join86 } from "node:path";
48671
48732
  function containerHookCommand() {
48672
- return join85(CONTAINER_AGENT_DIR, ".claude", "hooks", HOOK_FILENAME);
48733
+ return join86(CONTAINER_AGENT_DIR, ".claude", "hooks", HOOK_FILENAME);
48673
48734
  }
48674
48735
  function updatePromptHookScript() {
48675
48736
  return `#!/bin/bash
@@ -48735,14 +48796,14 @@ exit 0
48735
48796
  `;
48736
48797
  }
48737
48798
  function installUpdatePromptHook(agentDir) {
48738
- const hooksDir = join85(agentDir, ".claude", "hooks");
48739
- mkdirSync47(hooksDir, { recursive: true });
48740
- const scriptPath = join85(hooksDir, HOOK_FILENAME);
48799
+ const hooksDir = join86(agentDir, ".claude", "hooks");
48800
+ mkdirSync48(hooksDir, { recursive: true });
48801
+ const scriptPath = join86(hooksDir, HOOK_FILENAME);
48741
48802
  const desired = updatePromptHookScript();
48742
48803
  let installed = false;
48743
- const existing = existsSync83(scriptPath) ? readFileSync72(scriptPath, "utf-8") : "";
48804
+ const existing = existsSync84(scriptPath) ? readFileSync73(scriptPath, "utf-8") : "";
48744
48805
  if (existing !== desired) {
48745
- writeFileSync29(scriptPath, desired, { mode: 493 });
48806
+ writeFileSync30(scriptPath, desired, { mode: 493 });
48746
48807
  chmodSync12(scriptPath, 493);
48747
48808
  installed = true;
48748
48809
  } else {
@@ -48750,11 +48811,11 @@ function installUpdatePromptHook(agentDir) {
48750
48811
  chmodSync12(scriptPath, 493);
48751
48812
  } catch {}
48752
48813
  }
48753
- const settingsPath = join85(agentDir, ".claude", "settings.json");
48754
- if (!existsSync83(settingsPath)) {
48814
+ const settingsPath = join86(agentDir, ".claude", "settings.json");
48815
+ if (!existsSync84(settingsPath)) {
48755
48816
  return { scriptPath, settingsPath, installed };
48756
48817
  }
48757
- const raw = readFileSync72(settingsPath, "utf-8");
48818
+ const raw = readFileSync73(settingsPath, "utf-8");
48758
48819
  let parsed;
48759
48820
  try {
48760
48821
  parsed = JSON.parse(raw);
@@ -48790,7 +48851,7 @@ function installUpdatePromptHook(agentDir) {
48790
48851
  if (mutated) {
48791
48852
  hooks.UserPromptSubmit = list2;
48792
48853
  parsed.hooks = hooks;
48793
- writeFileSync29(settingsPath, JSON.stringify(parsed, null, 2) + `
48854
+ writeFileSync30(settingsPath, JSON.stringify(parsed, null, 2) + `
48794
48855
  `, { mode: 384 });
48795
48856
  installed = true;
48796
48857
  } else if (!alreadyCorrect) {
@@ -48799,7 +48860,7 @@ function installUpdatePromptHook(agentDir) {
48799
48860
  });
48800
48861
  hooks.UserPromptSubmit = list2;
48801
48862
  parsed.hooks = hooks;
48802
- writeFileSync29(settingsPath, JSON.stringify(parsed, null, 2) + `
48863
+ writeFileSync30(settingsPath, JSON.stringify(parsed, null, 2) + `
48803
48864
  `, { mode: 384 });
48804
48865
  installed = true;
48805
48866
  }
@@ -49183,8 +49244,8 @@ __export(exports_voice_sidecar_token, {
49183
49244
  VOICE_SIDECAR_TOKEN_ENV: () => VOICE_SIDECAR_TOKEN_ENV
49184
49245
  });
49185
49246
  import { randomBytes as randomBytes14 } from "node:crypto";
49186
- import { chmodSync as chmodSync13, chownSync as chownSync7, existsSync as existsSync85, mkdirSync as mkdirSync48, readFileSync as readFileSync73, rmSync as rmSync17, writeFileSync as writeFileSync30 } from "node:fs";
49187
- import { dirname as dirname29 } from "node:path";
49247
+ import { chmodSync as chmodSync13, chownSync as chownSync7, existsSync as existsSync86, mkdirSync as mkdirSync49, readFileSync as readFileSync74, rmSync as rmSync17, writeFileSync as writeFileSync31 } from "node:fs";
49248
+ import { dirname as dirname31 } from "node:path";
49188
49249
  async function defaultResolveOrSeedToken(home2, writeErr) {
49189
49250
  const [{ getViaBrokerStructured: getViaBrokerStructured2, putViaBroker: putViaBroker2 }, { resolveOperatorVaultPassphrase }] = await Promise.all([
49190
49251
  Promise.resolve().then(() => (init_client(), exports_client)),
@@ -49218,8 +49279,8 @@ async function provisionVoiceSidecarToken(composePath, home2, ctx) {
49218
49279
  const envPath = composeEnvPath(composePath);
49219
49280
  if (engine !== "local") {
49220
49281
  try {
49221
- if (existsSync85(envPath)) {
49222
- const body = readFileSync73(envPath, "utf-8");
49282
+ if (existsSync86(envPath)) {
49283
+ const body = readFileSync74(envPath, "utf-8");
49223
49284
  if (body.includes(`${VOICE_SIDECAR_TOKEN_ENV}=`))
49224
49285
  rmSync17(envPath);
49225
49286
  }
@@ -49238,11 +49299,11 @@ async function provisionVoiceSidecarToken(composePath, home2, ctx) {
49238
49299
  if (!token)
49239
49300
  return;
49240
49301
  try {
49241
- mkdirSync48(dirname29(envPath), { recursive: true });
49302
+ mkdirSync49(dirname31(envPath), { recursive: true });
49242
49303
  let body = "";
49243
49304
  try {
49244
- if (existsSync85(envPath))
49245
- body = readFileSync73(envPath, "utf-8");
49305
+ if (existsSync86(envPath))
49306
+ body = readFileSync74(envPath, "utf-8");
49246
49307
  } catch {}
49247
49308
  const line = `${VOICE_SIDECAR_TOKEN_ENV}=${token}`;
49248
49309
  const keyRe = new RegExp(`^${VOICE_SIDECAR_TOKEN_ENV}=.*$`, "m");
@@ -49250,7 +49311,7 @@ async function provisionVoiceSidecarToken(composePath, home2, ctx) {
49250
49311
  `) ? body + `
49251
49312
  ` : body) + line + `
49252
49313
  `;
49253
- writeFileSync30(envPath, next, {
49314
+ writeFileSync31(envPath, next, {
49254
49315
  encoding: "utf-8",
49255
49316
  mode: 384
49256
49317
  });
@@ -49302,11 +49363,11 @@ __export(exports_apply, {
49302
49363
  DEFAULT_COMPOSE_PATH: () => DEFAULT_COMPOSE_PATH2,
49303
49364
  COMPOSE_PROJECT: () => COMPOSE_PROJECT2
49304
49365
  });
49305
- import { accessSync as accessSync3, chmodSync as chmodSync14, chownSync as chownSync8, constants as fsConstants6, copyFileSync as copyFileSync12, existsSync as existsSync86, mkdirSync as mkdirSync49, readFileSync as readFileSync74, readdirSync as readdirSync30, renameSync as renameSync20, statSync as statSync47, writeFileSync as writeFileSync31 } from "node:fs";
49366
+ import { accessSync as accessSync3, chmodSync as chmodSync14, chownSync as chownSync8, constants as fsConstants6, copyFileSync as copyFileSync12, existsSync as existsSync87, mkdirSync as mkdirSync50, readFileSync as readFileSync75, readdirSync as readdirSync31, renameSync as renameSync21, statSync as statSync47, writeFileSync as writeFileSync32 } from "node:fs";
49306
49367
  import { mkdir as mkdir2 } from "node:fs/promises";
49307
49368
  import { spawnSync as childSpawnSync } from "node:child_process";
49308
49369
  import readline from "node:readline";
49309
- import { dirname as dirname30, join as join87, resolve as resolve52 } from "node:path";
49370
+ import { dirname as dirname32, join as join88, resolve as resolve52 } from "node:path";
49310
49371
  import { homedir as homedir49 } from "node:os";
49311
49372
  import { execFileSync as execFileSync27 } from "node:child_process";
49312
49373
  function effectiveLiteLLMEnabled(config, agentResolvedLitellm) {
@@ -49318,7 +49379,7 @@ async function resolveOperatorVaultPassphrase(home2) {
49318
49379
  return envPass;
49319
49380
  try {
49320
49381
  const { readAutoUnlockFile: readAutoUnlockFile2 } = await Promise.resolve().then(() => (init_auto_unlock(), exports_auto_unlock));
49321
- const blobPath = join87(home2, ".switchroom", "vault-auto-unlock");
49382
+ const blobPath = join88(home2, ".switchroom", "vault-auto-unlock");
49322
49383
  const pass = readAutoUnlockFile2(blobPath);
49323
49384
  return pass && pass.length > 0 ? pass : null;
49324
49385
  } catch {
@@ -49327,10 +49388,10 @@ async function resolveOperatorVaultPassphrase(home2) {
49327
49388
  }
49328
49389
  function materializeLitellmMasterKeyForBroker(masterKey, home2 = process.env.HOME ?? "/root") {
49329
49390
  try {
49330
- const stateDir = join87(home2, ".switchroom", "state", "auth-broker");
49331
- mkdirSync49(stateDir, { recursive: true, mode: 448 });
49332
- const path9 = join87(stateDir, LITELLM_MASTER_KEY_STATE_BASENAME);
49333
- writeFileSync31(path9, masterKey.trim() + `
49391
+ const stateDir = join88(home2, ".switchroom", "state", "auth-broker");
49392
+ mkdirSync50(stateDir, { recursive: true, mode: 448 });
49393
+ const path9 = join88(stateDir, LITELLM_MASTER_KEY_STATE_BASENAME);
49394
+ writeFileSync32(path9, masterKey.trim() + `
49334
49395
  `, { mode: 384 });
49335
49396
  try {
49336
49397
  chmodSync14(path9, 384);
@@ -49422,9 +49483,9 @@ async function provisionLiteLLMKeys(config, agentNames, switchroomConfigPath, ct
49422
49483
  const oauthAccount = config.auth?.active;
49423
49484
  let pendingConfigEdits = false;
49424
49485
  let configText = null;
49425
- if (switchroomConfigPath && existsSync86(switchroomConfigPath)) {
49486
+ if (switchroomConfigPath && existsSync87(switchroomConfigPath)) {
49426
49487
  try {
49427
- configText = readFileSync74(switchroomConfigPath, "utf-8");
49488
+ configText = readFileSync75(switchroomConfigPath, "utf-8");
49428
49489
  } catch (err) {
49429
49490
  ctx.writeErr(source_default.yellow(` ! litellm: could not read config for ACL grants (${err.message}); keys will be provisioned but agents may lack read-ACL.
49430
49491
  `));
@@ -49653,14 +49714,14 @@ async function provisionLiteLLMKeys(config, agentNames, switchroomConfigPath, ct
49653
49714
  function resolveVaultBindMountDir(homeDir, ctx) {
49654
49715
  const isCustomPath = ctx.migrationKind === "custom-path-skipped";
49655
49716
  if (isCustomPath && ctx.customVaultPath) {
49656
- return dirname30(ctx.customVaultPath);
49717
+ return dirname32(ctx.customVaultPath);
49657
49718
  }
49658
- return join87(homeDir, ".switchroom", "vault");
49719
+ return join88(homeDir, ".switchroom", "vault");
49659
49720
  }
49660
49721
  function inspectVaultBindMountDir(vaultDir) {
49661
- if (!existsSync86(vaultDir))
49722
+ if (!existsSync87(vaultDir))
49662
49723
  return { kind: "missing" };
49663
- const entries = readdirSync30(vaultDir);
49724
+ const entries = readdirSync31(vaultDir);
49664
49725
  const unknown = [];
49665
49726
  for (const name of entries) {
49666
49727
  if (KNOWN_VAULT_ARTIFACT_NAMES.has(name))
@@ -49686,60 +49747,60 @@ function hasVaultRefs(value) {
49686
49747
  async function ensureHostMountSources(config) {
49687
49748
  const home2 = resolveHostHomeForCompose();
49688
49749
  const dirs = [
49689
- join87(home2, ".switchroom", "approvals"),
49690
- join87(home2, ".switchroom", "scheduler"),
49691
- join87(home2, ".switchroom", "logs"),
49692
- join87(home2, ".switchroom", "compose"),
49693
- join87(home2, ".switchroom", "broker-operator")
49750
+ join88(home2, ".switchroom", "approvals"),
49751
+ join88(home2, ".switchroom", "scheduler"),
49752
+ join88(home2, ".switchroom", "logs"),
49753
+ join88(home2, ".switchroom", "compose"),
49754
+ join88(home2, ".switchroom", "broker-operator")
49694
49755
  ];
49695
49756
  for (const name of Object.keys(config.agents)) {
49696
- dirs.push(join87(home2, ".switchroom", "agents", name));
49697
- dirs.push(join87(home2, ".switchroom", "logs", name));
49698
- dirs.push(join87(home2, ".claude", "projects", name));
49699
- dirs.push(join87(home2, ".switchroom", "audit", name));
49700
- if (existsSync86(join87(home2, ".switchroom-config"))) {
49701
- dirs.push(join87(home2, ".switchroom-config", "agents", name, "personal-skills"));
49757
+ dirs.push(join88(home2, ".switchroom", "agents", name));
49758
+ dirs.push(join88(home2, ".switchroom", "logs", name));
49759
+ dirs.push(join88(home2, ".claude", "projects", name));
49760
+ dirs.push(join88(home2, ".switchroom", "audit", name));
49761
+ if (existsSync87(join88(home2, ".switchroom-config"))) {
49762
+ dirs.push(join88(home2, ".switchroom-config", "agents", name, "personal-skills"));
49702
49763
  }
49703
49764
  }
49704
49765
  for (const dir of dirs) {
49705
49766
  await mkdir2(dir, { recursive: true });
49706
49767
  }
49707
- const autoUnlockPath = join87(home2, ".switchroom", "vault-auto-unlock");
49708
- if (!existsSync86(autoUnlockPath)) {
49709
- writeFileSync31(autoUnlockPath, "", { mode: 384 });
49768
+ const autoUnlockPath = join88(home2, ".switchroom", "vault-auto-unlock");
49769
+ if (!existsSync87(autoUnlockPath)) {
49770
+ writeFileSync32(autoUnlockPath, "", { mode: 384 });
49710
49771
  }
49711
- const auditLogPath = join87(home2, ".switchroom", "vault-audit.log");
49712
- if (!existsSync86(auditLogPath)) {
49713
- writeFileSync31(auditLogPath, "", { mode: 420 });
49772
+ const auditLogPath = join88(home2, ".switchroom", "vault-audit.log");
49773
+ if (!existsSync87(auditLogPath)) {
49774
+ writeFileSync32(auditLogPath, "", { mode: 420 });
49714
49775
  }
49715
49776
  const grantsDbDir = getGrantsDbDir(home2);
49716
- mkdirSync49(grantsDbDir, { recursive: true, mode: 448 });
49777
+ mkdirSync50(grantsDbDir, { recursive: true, mode: 448 });
49717
49778
  migrateLegacyGrantsDbLocation(getGrantsDbPath(home2));
49718
- const hostdAuditLogPath = join87(home2, ".switchroom", "host-control-audit.log");
49719
- if (!existsSync86(hostdAuditLogPath)) {
49720
- writeFileSync31(hostdAuditLogPath, "", { mode: 420 });
49779
+ const hostdAuditLogPath = join88(home2, ".switchroom", "host-control-audit.log");
49780
+ if (!existsSync87(hostdAuditLogPath)) {
49781
+ writeFileSync32(hostdAuditLogPath, "", { mode: 420 });
49721
49782
  }
49722
49783
  for (const name of Object.keys(config.agents)) {
49723
- const tokenPath = join87(home2, ".switchroom", "agents", name, ".vault-token");
49724
- if (!existsSync86(tokenPath)) {
49725
- writeFileSync31(tokenPath, "", { mode: 384 });
49784
+ const tokenPath = join88(home2, ".switchroom", "agents", name, ".vault-token");
49785
+ if (!existsSync87(tokenPath)) {
49786
+ writeFileSync32(tokenPath, "", { mode: 384 });
49726
49787
  }
49727
49788
  try {
49728
49789
  const uid = allocateAgentUid(name);
49729
49790
  chownSync8(tokenPath, uid, uid);
49730
49791
  } catch {}
49731
49792
  }
49732
- const fleetDir = join87(home2, ".switchroom", "fleet");
49793
+ const fleetDir = join88(home2, ".switchroom", "fleet");
49733
49794
  await mkdir2(fleetDir, { recursive: true });
49734
- const invariantsPath = join87(fleetDir, "switchroom-invariants.md");
49795
+ const invariantsPath = join88(fleetDir, "switchroom-invariants.md");
49735
49796
  const invariantsCanonical = renderFleetInvariants();
49736
- const invariantsCurrent = existsSync86(invariantsPath) ? readFileSync74(invariantsPath, "utf-8") : null;
49797
+ const invariantsCurrent = existsSync87(invariantsPath) ? readFileSync75(invariantsPath, "utf-8") : null;
49737
49798
  if (invariantsCurrent !== invariantsCanonical) {
49738
- writeFileSync31(invariantsPath, invariantsCanonical, { mode: 420 });
49799
+ writeFileSync32(invariantsPath, invariantsCanonical, { mode: 420 });
49739
49800
  }
49740
- const fleetClaudePath = join87(fleetDir, "CLAUDE.md");
49741
- if (!existsSync86(fleetClaudePath)) {
49742
- writeFileSync31(fleetClaudePath, renderFleetDefaultsClaudeMd(), {
49801
+ const fleetClaudePath = join88(fleetDir, "CLAUDE.md");
49802
+ if (!existsSync87(fleetClaudePath)) {
49803
+ writeFileSync32(fleetClaudePath, renderFleetDefaultsClaudeMd(), {
49743
49804
  mode: 420
49744
49805
  });
49745
49806
  }
@@ -49768,7 +49829,7 @@ function isInAgentContainer(vaultPresent, composeV2Present, env2 = process.env)
49768
49829
  function runApplyPreflight(config, opts = {}) {
49769
49830
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
49770
49831
  const detect = opts.detectComposeV2 ?? detectComposeV2;
49771
- const vaultMissing = hasVaultRefs(config) && !existsSync86(vaultPath);
49832
+ const vaultMissing = hasVaultRefs(config) && !existsSync87(vaultPath);
49772
49833
  const composeErr = detect();
49773
49834
  if ((vaultMissing || composeErr) && isInAgentContainer(!vaultMissing, composeErr === null)) {
49774
49835
  throw new Error(IN_AGENT_CONTAINER_APPLY_MSG);
@@ -49782,7 +49843,7 @@ function runApplyPreflight(config, opts = {}) {
49782
49843
  detectAndReportLegacyGdriveSlots(vaultPath);
49783
49844
  }
49784
49845
  function detectAndReportLegacyGdriveSlots(vaultPath) {
49785
- if (!existsSync86(vaultPath))
49846
+ if (!existsSync87(vaultPath))
49786
49847
  return;
49787
49848
  const passphrase = process.env.SWITCHROOM_VAULT_PASSPHRASE;
49788
49849
  if (!passphrase)
@@ -49823,17 +49884,17 @@ function detectAndReportLegacyGdriveSlots(vaultPath) {
49823
49884
  }
49824
49885
  function writeInstallTypeCache(homeDir = homedir49()) {
49825
49886
  const ctx = detectInstallType();
49826
- const dir = join87(homeDir, ".switchroom");
49827
- const out = join87(dir, "install-type.json");
49887
+ const dir = join88(homeDir, ".switchroom");
49888
+ const out = join88(dir, "install-type.json");
49828
49889
  const tmp = `${out}.tmp`;
49829
- mkdirSync49(dir, { recursive: true });
49890
+ mkdirSync50(dir, { recursive: true });
49830
49891
  const payload = {
49831
49892
  install_type: ctx.install_type,
49832
49893
  detected_at: new Date().toISOString(),
49833
49894
  source_paths: ctx.source_paths
49834
49895
  };
49835
- writeFileSync31(tmp, JSON.stringify(payload, null, 2), { mode: 420 });
49836
- renameSync20(tmp, out);
49896
+ writeFileSync32(tmp, JSON.stringify(payload, null, 2), { mode: 420 });
49897
+ renameSync21(tmp, out);
49837
49898
  return out;
49838
49899
  }
49839
49900
  async function runApply(config, options, deps = {}, switchroomConfigPath) {
@@ -49891,17 +49952,17 @@ Applying switchroom config...
49891
49952
  writeOut(source_default.green(` + ${name}`) + source_default.gray(` (${agentConfig.extends ?? "default"}) \u2014 ${detail}
49892
49953
  `));
49893
49954
  try {
49894
- installUpdatePromptHook(join87(agentsDir, name));
49955
+ installUpdatePromptHook(join88(agentsDir, name));
49895
49956
  } catch (hookErr) {
49896
49957
  writeOut(source_default.gray(` (update-prompt hook install failed for ${name}: ${hookErr.message})
49897
49958
  `));
49898
49959
  }
49899
- await refreshAgentConnectionHealth(config, name, join87(agentsDir, name), {
49960
+ await refreshAgentConnectionHealth(config, name, join88(agentsDir, name), {
49900
49961
  vaultAclReader: connHealthVaultAclReader
49901
49962
  });
49902
49963
  try {
49903
49964
  const uid = allocateAgentUid(name);
49904
- alignAgentUid(name, join87(agentsDir, name), uid, {
49965
+ alignAgentUid(name, join88(agentsDir, name), uid, {
49905
49966
  confirm: !options.nonInteractive,
49906
49967
  writeOut
49907
49968
  });
@@ -49946,7 +50007,7 @@ Applying switchroom config...
49946
50007
  for (const name of agentNames) {
49947
50008
  try {
49948
50009
  const uid = allocateAgentUid(name);
49949
- alignAgentUid(name, join87(agentsDir, name), uid, {
50010
+ alignAgentUid(name, join88(agentsDir, name), uid, {
49950
50011
  confirm: !options.nonInteractive,
49951
50012
  writeOut
49952
50013
  });
@@ -50284,18 +50345,18 @@ function copyExampleConfig2(name) {
50284
50345
  throw new Error(`Invalid example name: ${name} (must match /^[a-z0-9_-]+$/)`);
50285
50346
  }
50286
50347
  const dest = resolve52(process.cwd(), "switchroom.yaml");
50287
- if (existsSync86(dest)) {
50348
+ if (existsSync87(dest)) {
50288
50349
  console.error(source_default.yellow("switchroom.yaml already exists \u2014 skipping example copy"));
50289
50350
  return;
50290
50351
  }
50291
50352
  const embedded = EMBEDDED_EXAMPLES[name];
50292
50353
  if (embedded !== undefined) {
50293
- writeFileSync31(dest, embedded, { encoding: "utf8" });
50354
+ writeFileSync32(dest, embedded, { encoding: "utf8" });
50294
50355
  console.log(source_default.green(`Copied ${name}.yaml -> switchroom.yaml`));
50295
50356
  return;
50296
50357
  }
50297
50358
  const exampleFile = resolve52(import.meta.dirname, `../../examples/${name}.yaml`);
50298
- if (!existsSync86(exampleFile)) {
50359
+ if (!existsSync87(exampleFile)) {
50299
50360
  throw new Error(`Example config not found: ${name}.yaml (available: ${Object.keys(EMBEDDED_EXAMPLES).join(", ")})`);
50300
50361
  }
50301
50362
  copyFileSync12(exampleFile, dest);
@@ -50306,8 +50367,8 @@ function findUnwritableAgentDirs(config, opts) {
50306
50367
  const targets = opts.only ? [opts.only] : Object.keys(config.agents ?? {});
50307
50368
  const unwritable = [];
50308
50369
  for (const name of targets) {
50309
- const startSh = join87(agentsDir, name, "start.sh");
50310
- if (!existsSync86(startSh))
50370
+ const startSh = join88(agentsDir, name, "start.sh");
50371
+ if (!existsSync87(startSh))
50311
50372
  continue;
50312
50373
  try {
50313
50374
  accessSync3(startSh, fsConstants6.W_OK);
@@ -50512,7 +50573,7 @@ var init_apply = __esm(() => {
50512
50573
  switchroom: switchroom_default,
50513
50574
  minimal: minimal_default
50514
50575
  };
50515
- DEFAULT_COMPOSE_PATH2 = join87(homedir49(), ".switchroom", "compose", "docker-compose.yml");
50576
+ DEFAULT_COMPOSE_PATH2 = join88(homedir49(), ".switchroom", "compose", "docker-compose.yml");
50516
50577
  IN_AGENT_CONTAINER_APPLY_MSG = "`switchroom apply`'s full per-agent scaffold cannot run from inside an " + "agent container \u2014 this is a host/hostd operation by construction " + "(no vault at the container HOME, and no `docker compose` v2 plugin here).\nTo roll the fleet to a new version, drive the hostd rollout (`mcp__hostd__rollout`): it runs a `--compose-only` apply plus a per-agent restart-reconcile, and each agent refreshes its own templates " + `on restart \u2014 the roll completes without any agent running a full apply.
50517
50578
  ` + "A full host-side `sudo switchroom apply` is only needed for structural changes (compose regeneration / new-agent scaffolding), and is run by the operator on the host, never from inside an agent.";
50518
50579
  SELF_ELEVATE_PRESERVED_ENV = [
@@ -59823,49 +59884,49 @@ var require_fast_uri = __commonJS((exports2, module) => {
59823
59884
  schemelessOptions.skipEscape = true;
59824
59885
  return serialize(resolved, schemelessOptions);
59825
59886
  }
59826
- function resolveComponent(base, relative4, options, skipNormalization) {
59887
+ function resolveComponent(base, relative6, options, skipNormalization) {
59827
59888
  const target = {};
59828
59889
  if (!skipNormalization) {
59829
59890
  base = parse6(serialize(base, options), options);
59830
- relative4 = parse6(serialize(relative4, options), options);
59891
+ relative6 = parse6(serialize(relative6, options), options);
59831
59892
  }
59832
59893
  options = options || {};
59833
- if (!options.tolerant && relative4.scheme) {
59834
- target.scheme = relative4.scheme;
59835
- target.userinfo = relative4.userinfo;
59836
- target.host = relative4.host;
59837
- target.port = relative4.port;
59838
- target.path = removeDotSegments(relative4.path || "");
59839
- target.query = relative4.query;
59894
+ if (!options.tolerant && relative6.scheme) {
59895
+ target.scheme = relative6.scheme;
59896
+ target.userinfo = relative6.userinfo;
59897
+ target.host = relative6.host;
59898
+ target.port = relative6.port;
59899
+ target.path = removeDotSegments(relative6.path || "");
59900
+ target.query = relative6.query;
59840
59901
  } else {
59841
- if (relative4.userinfo !== undefined || relative4.host !== undefined || relative4.port !== undefined) {
59842
- target.userinfo = relative4.userinfo;
59843
- target.host = relative4.host;
59844
- target.port = relative4.port;
59845
- target.path = removeDotSegments(relative4.path || "");
59846
- target.query = relative4.query;
59902
+ if (relative6.userinfo !== undefined || relative6.host !== undefined || relative6.port !== undefined) {
59903
+ target.userinfo = relative6.userinfo;
59904
+ target.host = relative6.host;
59905
+ target.port = relative6.port;
59906
+ target.path = removeDotSegments(relative6.path || "");
59907
+ target.query = relative6.query;
59847
59908
  } else {
59848
- if (!relative4.path) {
59909
+ if (!relative6.path) {
59849
59910
  target.path = base.path;
59850
- if (relative4.query !== undefined) {
59851
- target.query = relative4.query;
59911
+ if (relative6.query !== undefined) {
59912
+ target.query = relative6.query;
59852
59913
  } else {
59853
59914
  target.query = base.query;
59854
59915
  }
59855
59916
  } else {
59856
- if (relative4.path[0] === "/") {
59857
- target.path = removeDotSegments(relative4.path);
59917
+ if (relative6.path[0] === "/") {
59918
+ target.path = removeDotSegments(relative6.path);
59858
59919
  } else {
59859
59920
  if ((base.userinfo !== undefined || base.host !== undefined || base.port !== undefined) && !base.path) {
59860
- target.path = "/" + relative4.path;
59921
+ target.path = "/" + relative6.path;
59861
59922
  } else if (!base.path) {
59862
- target.path = relative4.path;
59923
+ target.path = relative6.path;
59863
59924
  } else {
59864
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative4.path;
59925
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative6.path;
59865
59926
  }
59866
59927
  target.path = removeDotSegments(target.path);
59867
59928
  }
59868
- target.query = relative4.query;
59929
+ target.query = relative6.query;
59869
59930
  }
59870
59931
  target.userinfo = base.userinfo;
59871
59932
  target.host = base.host;
@@ -59873,7 +59934,7 @@ var require_fast_uri = __commonJS((exports2, module) => {
59873
59934
  }
59874
59935
  target.scheme = base.scheme;
59875
59936
  }
59876
- target.fragment = relative4.fragment;
59937
+ target.fragment = relative6.fragment;
59877
59938
  return target;
59878
59939
  }
59879
59940
  function equal(uriA, uriB, options) {
@@ -63961,7 +64022,7 @@ __export(exports_server2, {
63961
64022
  TOOLS: () => TOOLS2
63962
64023
  });
63963
64024
  import { randomBytes as randomBytes16 } from "node:crypto";
63964
- import { existsSync as existsSync95, readFileSync as readFileSync83 } from "node:fs";
64025
+ import { existsSync as existsSync96, readFileSync as readFileSync84 } from "node:fs";
63965
64026
  function selfSocketPath() {
63966
64027
  return `/run/switchroom/hostd/${SELF_AGENT}/sock`;
63967
64028
  }
@@ -63988,7 +64049,7 @@ async function dispatchTool2(name, args) {
63988
64049
  return errorText2("hostd MCP: SWITCHROOM_AGENT_NAME env var is not set \u2014 cannot " + "determine which per-agent socket to talk to.");
63989
64050
  }
63990
64051
  const sockPath = selfSocketPath();
63991
- if (!existsSync95(sockPath)) {
64052
+ if (!existsSync96(sockPath)) {
63992
64053
  return errorText2(`hostd MCP: socket not bound at ${sockPath}. The host-control ` + `daemon is either not installed (run \`switchroom hostd install\`) ` + `or this agent isn't admin-flagged in switchroom.yaml. RFC C ` + `bind-mounts the per-agent socket only when host_control.enabled ` + `is true AND the agent has admin: true.`);
63993
64054
  }
63994
64055
  let req;
@@ -64239,18 +64300,18 @@ function resolveAuditLogPath() {
64239
64300
  if (process.env.HOSTD_AUDIT_LOG_PATH)
64240
64301
  return process.env.HOSTD_AUDIT_LOG_PATH;
64241
64302
  const bindMounted = "/host-home/.switchroom/host-control-audit.log";
64242
- if (existsSync95(bindMounted))
64303
+ if (existsSync96(bindMounted))
64243
64304
  return bindMounted;
64244
64305
  return defaultAuditLogPath2();
64245
64306
  }
64246
64307
  function getLastUpdateApplyStatus() {
64247
64308
  const path9 = resolveAuditLogPath();
64248
- if (!existsSync95(path9)) {
64309
+ if (!existsSync96(path9)) {
64249
64310
  return errorText2(`get_status: audit log not found at ${path9}. No update_apply has run yet?`);
64250
64311
  }
64251
64312
  let raw;
64252
64313
  try {
64253
- raw = readFileSync83(path9, "utf-8");
64314
+ raw = readFileSync84(path9, "utf-8");
64254
64315
  } catch (err2) {
64255
64316
  return errorText2(`get_status: failed to read audit log at ${path9}: ${err2.message}`);
64256
64317
  }
@@ -65000,14 +65061,14 @@ var init_header_passthrough_guard = __esm(() => {
65000
65061
  });
65001
65062
 
65002
65063
  // src/fleet-health/litellm-config-sensor.ts
65003
- import { readFileSync as readFileSync85, existsSync as existsSync98 } from "node:fs";
65064
+ import { readFileSync as readFileSync86, existsSync as existsSync99 } from "node:fs";
65004
65065
  function resolveLitellmConfigPath(explicit) {
65005
65066
  return explicit ?? process.env.LITELLM_CONFIG_PATH ?? DEFAULT_LITELLM_CONFIG_PATH;
65006
65067
  }
65007
65068
  function scanLitellmConfig(opts = {}) {
65008
65069
  const path9 = resolveLitellmConfigPath(opts.path);
65009
- const exists = opts.existsFn ?? existsSync98;
65010
- const read = opts.readFn ?? ((p) => readFileSync85(p, "utf-8"));
65070
+ const exists = opts.existsFn ?? existsSync99;
65071
+ const read = opts.readFn ?? ((p) => readFileSync86(p, "utf-8"));
65011
65072
  const log = opts.log ?? (() => {});
65012
65073
  const nowIso = opts.nowIso ?? new Date().toISOString();
65013
65074
  if (!exists(path9)) {
@@ -65062,23 +65123,23 @@ __export(exports_scan, {
65062
65123
  ledgerPathForBase: () => ledgerPathForBase
65063
65124
  });
65064
65125
  import {
65065
- readFileSync as readFileSync86,
65066
- readdirSync as readdirSync38,
65067
- existsSync as existsSync99,
65068
- mkdirSync as mkdirSync56,
65069
- writeFileSync as writeFileSync37
65126
+ readFileSync as readFileSync87,
65127
+ readdirSync as readdirSync39,
65128
+ existsSync as existsSync100,
65129
+ mkdirSync as mkdirSync57,
65130
+ writeFileSync as writeFileSync38
65070
65131
  } from "node:fs";
65071
- import { resolve as resolve57, dirname as dirname33 } from "node:path";
65132
+ import { resolve as resolve57, dirname as dirname35 } from "node:path";
65072
65133
  import { homedir as homedir58 } from "node:os";
65073
65134
  function resolveSwitchroomBase(home2 = process.env.SWITCHROOM_HOME ?? process.env.HOME ?? homedir58()) {
65074
65135
  return resolve57(home2, ".switchroom");
65075
65136
  }
65076
65137
  function listAgents(base) {
65077
65138
  const dir = resolve57(base, "agents");
65078
- if (!existsSync99(dir))
65139
+ if (!existsSync100(dir))
65079
65140
  return [];
65080
65141
  try {
65081
- return readdirSync38(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
65142
+ return readdirSync39(dir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name).sort();
65082
65143
  } catch {
65083
65144
  return [];
65084
65145
  }
@@ -65104,16 +65165,16 @@ function runScan(opts = {}) {
65104
65165
  let gwText = "";
65105
65166
  let sawArtifact = false;
65106
65167
  try {
65107
- if (existsSync99(turnsPath)) {
65108
- turnsText = readFileSync86(turnsPath, "utf-8");
65168
+ if (existsSync100(turnsPath)) {
65169
+ turnsText = readFileSync87(turnsPath, "utf-8");
65109
65170
  sawArtifact = true;
65110
65171
  }
65111
65172
  } catch (e) {
65112
65173
  log(`fleet-health: WARN skipping ${agent} turns.jsonl unreadable: ${String(e)}`);
65113
65174
  }
65114
65175
  try {
65115
- if (existsSync99(gwPath)) {
65116
- gwText = readFileSync86(gwPath, "utf-8");
65176
+ if (existsSync100(gwPath)) {
65177
+ gwText = readFileSync87(gwPath, "utf-8");
65117
65178
  sawArtifact = true;
65118
65179
  }
65119
65180
  } catch (e) {
@@ -65155,20 +65216,20 @@ function runScan(opts = {}) {
65155
65216
  function readLedgerIfPresent(base) {
65156
65217
  const path9 = ledgerPathForBase(base);
65157
65218
  try {
65158
- if (!existsSync99(path9))
65219
+ if (!existsSync100(path9))
65159
65220
  return null;
65160
- return JSON.parse(readFileSync86(path9, "utf-8"));
65221
+ return JSON.parse(readFileSync87(path9, "utf-8"));
65161
65222
  } catch {
65162
65223
  return null;
65163
65224
  }
65164
65225
  }
65165
65226
  function ledgerPathForBase(base) {
65166
- return fleetHealthLedgerPath(dirname33(base));
65227
+ return fleetHealthLedgerPath(dirname35(base));
65167
65228
  }
65168
65229
  function writeLedger(base, ledger) {
65169
65230
  const path9 = ledgerPathForBase(base);
65170
- mkdirSync56(dirname33(path9), { recursive: true });
65171
- writeFileSync37(path9, JSON.stringify(ledger, null, 2) + `
65231
+ mkdirSync57(dirname35(path9), { recursive: true });
65232
+ writeFileSync38(path9, JSON.stringify(ledger, null, 2) + `
65172
65233
  `, "utf-8");
65173
65234
  return path9;
65174
65235
  }
@@ -72174,7 +72235,7 @@ init_audit_log();
72174
72235
  init_test_isolation_guard();
72175
72236
  import * as net3 from "node:net";
72176
72237
  import { mkdirSync as mkdirSync25, chmodSync as chmodSync9, chownSync as chownSync4, existsSync as existsSync43, readFileSync as readFileSync35, readdirSync as readdirSync18, statSync as statSync26, unlinkSync as unlinkSync10, writeFileSync as writeFileSync14, renameSync as renameSync14 } from "node:fs";
72177
- import { dirname as dirname13, resolve as resolve29, basename as basename7 } from "node:path";
72238
+ import { dirname as dirname15, resolve as resolve29, basename as basename7 } from "node:path";
72178
72239
  import * as os4 from "node:os";
72179
72240
  import * as path4 from "node:path";
72180
72241
 
@@ -74550,7 +74611,7 @@ class VaultBroker {
74550
74611
  this.passphrase = this.testOpts._testPassphrase;
74551
74612
  }
74552
74613
  process.umask(63);
74553
- const parentDir = dirname13(this.socketPath);
74614
+ const parentDir = dirname15(this.socketPath);
74554
74615
  mkdirSync25(parentDir, { recursive: true, mode: 448 });
74555
74616
  try {
74556
74617
  chmodSync9(parentDir, 448);
@@ -76095,15 +76156,15 @@ class VaultBroker {
76095
76156
  }
76096
76157
  }
76097
76158
  function detectVaultLayoutDrift(vaultPath) {
76098
- const dir = dirname13(vaultPath);
76159
+ const dir = dirname15(vaultPath);
76099
76160
  if (basename7(dir) !== "vault")
76100
76161
  return;
76101
76162
  if (basename7(vaultPath) !== "vault.enc")
76102
76163
  return;
76103
- const switchroomDir = dirname13(dir);
76164
+ const switchroomDir = dirname15(dir);
76104
76165
  if (basename7(switchroomDir) !== ".switchroom")
76105
76166
  return;
76106
- const home2 = dirname13(switchroomDir);
76167
+ const home2 = dirname15(switchroomDir);
76107
76168
  const result = inspectVaultLayout(home2);
76108
76169
  if (result.kind === "divergent") {
76109
76170
  throw new VaultError(`Vault layout divergence detected at boot: ${result.details.oldPath} and ${result.details.newPath} are both regular files with different content. An older switchroom CLI may have written to the legacy path after migration ran. Run \`switchroom apply\` from the host to surface the recovery recipe (state E refusal with literal \`mv\` commands). See docs/operators/state-e-recovery.md.`);
@@ -79584,7 +79645,7 @@ import {
79584
79645
  writeSync as writeSync8,
79585
79646
  constants as fsConstants3
79586
79647
  } from "node:fs";
79587
- import { resolve as resolve34, extname, join as join51, relative, dirname as dirname16 } from "node:path";
79648
+ import { resolve as resolve34, extname, join as join51, relative as relative3, dirname as dirname18 } from "node:path";
79588
79649
  import { homedir as homedir28 } from "node:os";
79589
79650
  import { timingSafeEqual as timingSafeEqual3, randomBytes as randomBytes11 } from "node:crypto";
79590
79651
 
@@ -83045,7 +83106,7 @@ function resolveWebToken() {
83045
83106
  return existing;
83046
83107
  }
83047
83108
  const token = randomBytes11(32).toString("hex");
83048
- mkdirSync31(dirname16(tokenPath), { recursive: true, mode: 448 });
83109
+ mkdirSync31(dirname18(tokenPath), { recursive: true, mode: 448 });
83049
83110
  try {
83050
83111
  const fd = openSync11(tokenPath, fsConstants3.O_WRONLY | fsConstants3.O_CREAT | fsConstants3.O_EXCL, 384);
83051
83112
  try {
@@ -83632,7 +83693,7 @@ function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
83632
83693
  } catch {
83633
83694
  return new Response("Not Found", { status: 404 });
83634
83695
  }
83635
- const rel = relative(uiDir, realFullPath);
83696
+ const rel = relative3(uiDir, realFullPath);
83636
83697
  if (rel.startsWith("..") || resolve34(uiDir, rel) !== realFullPath) {
83637
83698
  return new Response("Forbidden", { status: 403 });
83638
83699
  }
@@ -83762,7 +83823,7 @@ init_loader();
83762
83823
 
83763
83824
  // src/web/startup-guard.ts
83764
83825
  import { existsSync as existsSync58, readFileSync as readFileSync53, writeFileSync as writeFileSync18, mkdirSync as mkdirSync32, statSync as statSync33, unlinkSync as unlinkSync13 } from "node:fs";
83765
- import { dirname as dirname17 } from "node:path";
83826
+ import { dirname as dirname19 } from "node:path";
83766
83827
  function detectConfigMountFault(configPath, deps = {}) {
83767
83828
  const stat = deps.stat ?? ((p) => statSync33(p));
83768
83829
  let st;
@@ -83809,7 +83870,7 @@ function readCrashState(statePath) {
83809
83870
  }
83810
83871
  function writeCrashState(statePath, state) {
83811
83872
  try {
83812
- mkdirSync32(dirname17(statePath), { recursive: true });
83873
+ mkdirSync32(dirname19(statePath), { recursive: true });
83813
83874
  writeFileSync18(statePath, JSON.stringify(state), { mode: 384 });
83814
83875
  } catch {}
83815
83876
  }
@@ -83905,7 +83966,7 @@ init_atomic();
83905
83966
  init_loader();
83906
83967
  init_scaffold();
83907
83968
  import { existsSync as existsSync59, copyFileSync as copyFileSync9, readFileSync as readFileSync54, mkdirSync as mkdirSync33, statSync as statSync34 } from "node:fs";
83908
- import { resolve as resolve35, dirname as dirname18 } from "node:path";
83969
+ import { resolve as resolve35, dirname as dirname20 } from "node:path";
83909
83970
  init_state();
83910
83971
  init_vault();
83911
83972
  init_manager();
@@ -84217,7 +84278,7 @@ async function copyExampleConfig(nonInteractive) {
84217
84278
  if (!existsSync59(srcFile)) {
84218
84279
  throw new ConfigError(`Example config not found: ${choice}.yaml`);
84219
84280
  }
84220
- mkdirSync33(dirname18(destFile), { recursive: true });
84281
+ mkdirSync33(dirname20(destFile), { recursive: true });
84221
84282
  copyFileSync9(srcFile, destFile);
84222
84283
  console.log(source_default.green(` Copied ${choice}.yaml -> ${destFile}`));
84223
84284
  console.log(source_default.yellow(` Edit ${destFile} to customize, then re-run switchroom setup.`));
@@ -84997,9 +85058,9 @@ init_source();
84997
85058
  init_loader();
84998
85059
  init_lifecycle();
84999
85060
  init_compose_env();
85000
- import { cpSync as cpSync2, existsSync as existsSync67, mkdirSync as mkdirSync35, readFileSync as readFileSync60, realpathSync as realpathSync6, rmSync as rmSync12, statSync as statSync40, chownSync as chownSync5 } from "node:fs";
85061
+ import { existsSync as existsSync68, mkdirSync as mkdirSync36, readFileSync as readFileSync61, realpathSync as realpathSync6, statSync as statSync40, chownSync as chownSync5 } from "node:fs";
85001
85062
  import { spawnSync as spawnSync12 } from "node:child_process";
85002
- import { join as join69, dirname as dirname21, resolve as resolve40 } from "node:path";
85063
+ import { join as join70, dirname as dirname23, resolve as resolve40 } from "node:path";
85003
85064
  import { homedir as homedir40 } from "node:os";
85004
85065
 
85005
85066
  // src/cli/release-yaml.ts
@@ -85090,10 +85151,132 @@ ${lines.join(`
85090
85151
 
85091
85152
  // src/cli/update.ts
85092
85153
  init_hindsight();
85154
+ init_scaffold_integration();
85155
+
85156
+ // src/cli/sync-bundled-skills.ts
85157
+ import {
85158
+ cpSync as cpSync2,
85159
+ existsSync as existsSync67,
85160
+ mkdirSync as mkdirSync35,
85161
+ readFileSync as readFileSync60,
85162
+ readdirSync as readdirSync24,
85163
+ renameSync as renameSync16,
85164
+ rmSync as rmSync12,
85165
+ writeFileSync as writeFileSync19
85166
+ } from "node:fs";
85167
+ import { join as join69 } from "node:path";
85168
+ var BUNDLED_SKILL_MANIFEST_NAME = ".switchroom-manifest.json";
85169
+ function listSkillDirs(dir) {
85170
+ if (!existsSync67(dir))
85171
+ return [];
85172
+ return readdirSync24(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
85173
+ }
85174
+ function readBundledSkillManifest(poolDir) {
85175
+ const path5 = join69(poolDir, BUNDLED_SKILL_MANIFEST_NAME);
85176
+ if (!existsSync67(path5))
85177
+ return { firstRun: true };
85178
+ try {
85179
+ const parsed = JSON.parse(readFileSync60(path5, "utf8"));
85180
+ if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.skills) || !parsed.skills.every((s) => typeof s === "string")) {
85181
+ return { corrupt: true };
85182
+ }
85183
+ const m = parsed;
85184
+ return { manifest: { version: String(m.version ?? ""), skills: m.skills, updatedAt: String(m.updatedAt ?? "") } };
85185
+ } catch {
85186
+ return { corrupt: true };
85187
+ }
85188
+ }
85189
+ function stageAndSwap(srcSkill, destSkill, poolDir, name) {
85190
+ const staging = join69(poolDir, `.tmp-${name}-${process.pid}-${Date.now()}`);
85191
+ try {
85192
+ rmSync12(staging, { recursive: true, force: true });
85193
+ cpSync2(srcSkill, staging, { recursive: true, dereference: false });
85194
+ rmSync12(destSkill, { recursive: true, force: true });
85195
+ renameSync16(staging, destSkill);
85196
+ } finally {
85197
+ rmSync12(staging, { recursive: true, force: true });
85198
+ }
85199
+ }
85200
+ function syncBundledSkills(opts) {
85201
+ const { source, dest, version: version2 } = opts;
85202
+ const result = {
85203
+ added: [],
85204
+ updated: [],
85205
+ removed: [],
85206
+ preserved: [],
85207
+ ownershipTransferred: [],
85208
+ firstRun: false,
85209
+ manifestCorrupt: false
85210
+ };
85211
+ mkdirSync35(dest, { recursive: true });
85212
+ const prior = readBundledSkillManifest(dest);
85213
+ const priorSkills = new Set("manifest" in prior ? prior.manifest.skills : []);
85214
+ result.firstRun = "firstRun" in prior;
85215
+ result.manifestCorrupt = "corrupt" in prior;
85216
+ const shipped = listSkillDirs(source).sort();
85217
+ const shippedSet = new Set(shipped);
85218
+ for (const name of shipped) {
85219
+ const destSkill = join69(dest, name);
85220
+ const existed = existsSync67(destSkill);
85221
+ let transferred = false;
85222
+ if (existed && !priorSkills.has(name) && !result.firstRun) {
85223
+ const backup = join69(dest, `${name}.operator-backup-${process.pid}-${Date.now()}`);
85224
+ try {
85225
+ renameSync16(destSkill, backup);
85226
+ transferred = true;
85227
+ result.ownershipTransferred.push(name);
85228
+ process.stderr.write(`switchroom: WARNING \u2014 a shipped skill "${name}" collides with an ` + `operator-added pool dir of the same name. Preserved the existing ` + `content as "${backup}" and installed the shipped skill under "${name}". ` + `If you meant to keep your version, rename it to a distinct skill name.
85229
+ `);
85230
+ } catch {
85231
+ result.ownershipTransferred.push(name);
85232
+ process.stderr.write(`switchroom: WARNING \u2014 shipped skill "${name}" collides with an ` + `operator-added pool dir and the preservation backup failed; left the ` + `existing dir in place and did NOT install the shipped skill. Resolve ` + `the name collision manually.
85233
+ `);
85234
+ continue;
85235
+ }
85236
+ }
85237
+ stageAndSwap(join69(source, name), destSkill, dest, name);
85238
+ if (!transferred && (priorSkills.has(name) || existed))
85239
+ result.updated.push(name);
85240
+ else
85241
+ result.added.push(name);
85242
+ }
85243
+ if (!result.firstRun && !result.manifestCorrupt) {
85244
+ for (const name of priorSkills) {
85245
+ if (shippedSet.has(name))
85246
+ continue;
85247
+ const target = join69(dest, name);
85248
+ if (existsSync67(target)) {
85249
+ rmSync12(target, { recursive: true, force: true });
85250
+ result.removed.push(name);
85251
+ }
85252
+ }
85253
+ }
85254
+ for (const name of listSkillDirs(dest)) {
85255
+ if (!shippedSet.has(name) && !priorSkills.has(name)) {
85256
+ result.preserved.push(name);
85257
+ }
85258
+ }
85259
+ result.removed.sort();
85260
+ result.preserved.sort();
85261
+ const manifest = {
85262
+ version: version2,
85263
+ skills: shipped,
85264
+ updatedAt: new Date().toISOString()
85265
+ };
85266
+ const manifestPath = join69(dest, BUNDLED_SKILL_MANIFEST_NAME);
85267
+ const manifestTmp = join69(dest, `${BUNDLED_SKILL_MANIFEST_NAME}.tmp-${process.pid}-${Date.now()}`);
85268
+ writeFileSync19(manifestTmp, JSON.stringify(manifest, null, 2) + `
85269
+ `, "utf8");
85270
+ renameSync16(manifestTmp, manifestPath);
85271
+ return result;
85272
+ }
85273
+
85274
+ // src/cli/update.ts
85275
+ init_resolve_version();
85093
85276
  function defaultPersistPin(configPath) {
85094
85277
  return (pin) => {
85095
85278
  const path5 = configPath ?? findConfigFile();
85096
- const before = readFileSync60(path5, "utf8");
85279
+ const before = readFileSync61(path5, "utf8");
85097
85280
  const after = setReleasePinInConfig(before, pin);
85098
85281
  if (after === before)
85099
85282
  return;
@@ -85107,18 +85290,18 @@ function defaultPersistPin(configPath) {
85107
85290
  } catch {}
85108
85291
  };
85109
85292
  }
85110
- var DEFAULT_COMPOSE_PATH = join69(homedir40(), ".switchroom", "compose", "docker-compose.yml");
85293
+ var DEFAULT_COMPOSE_PATH = join70(homedir40(), ".switchroom", "compose", "docker-compose.yml");
85111
85294
  function runningFromSwitchroomCheckout(scriptPath) {
85112
- let dir = dirname21(scriptPath);
85295
+ let dir = dirname23(scriptPath);
85113
85296
  for (let i = 0;i < 12; i++) {
85114
- if (existsSync67(join69(dir, ".git"))) {
85297
+ if (existsSync68(join70(dir, ".git"))) {
85115
85298
  try {
85116
- const pkg = JSON.parse(readFileSync60(join69(dir, "package.json"), "utf-8"));
85299
+ const pkg = JSON.parse(readFileSync61(join70(dir, "package.json"), "utf-8"));
85117
85300
  if (pkg.name === "switchroom")
85118
85301
  return true;
85119
85302
  } catch {}
85120
85303
  }
85121
- const parent = dirname21(dir);
85304
+ const parent = dirname23(dir);
85122
85305
  if (parent === dir)
85123
85306
  break;
85124
85307
  dir = parent;
@@ -85198,7 +85381,7 @@ function planUpdate(opts) {
85198
85381
  steps.push({
85199
85382
  name: "pull-images",
85200
85383
  description: "Pull broker / kernel / agent images from GHCR",
85201
- skipReason: opts.skipImages ? "--skip-images flag set" : !existsSync67(composePath) ? `compose file not found at ${composePath} (run \`switchroom apply --compose-only\` first)` : undefined,
85384
+ skipReason: opts.skipImages ? "--skip-images flag set" : !existsSync68(composePath) ? `compose file not found at ${composePath} (run \`switchroom apply --compose-only\` first)` : undefined,
85202
85385
  run: () => {
85203
85386
  const r = runner("docker", [
85204
85387
  "compose",
@@ -85324,23 +85507,48 @@ function planUpdate(opts) {
85324
85507
  return;
85325
85508
  }
85326
85509
  const source = resolve40(import.meta.dirname, "../../skills");
85327
- const dest = join69(homedir40(), ".switchroom", "skills", "_bundled");
85328
- if (!existsSync67(source)) {
85510
+ const dest = join70(homedir40(), ".switchroom", "skills", "_bundled");
85511
+ if (!existsSync68(source)) {
85329
85512
  process.stderr.write(`switchroom update: sync-bundled-skills \u2014 CLI bundle has no adjacent skills/ at ${source}; skipping.
85330
85513
  `);
85331
85514
  return;
85332
85515
  }
85333
85516
  try {
85334
- if (existsSync67(dest)) {
85335
- rmSync12(dest, { recursive: true, force: true });
85517
+ mkdirSync36(dirname23(dest), { recursive: true });
85518
+ const r = syncBundledSkills({
85519
+ source,
85520
+ dest,
85521
+ version: SWITCHROOM_VERSION
85522
+ });
85523
+ if (r.manifestCorrupt) {
85524
+ process.stderr.write(`switchroom update: sync-bundled-skills \u2014 pool manifest was unreadable; ` + `deleted nothing (fail-closed) and rewrote a clean manifest.
85525
+ `);
85526
+ }
85527
+ if (r.removed.length > 0) {
85528
+ process.stderr.write(`switchroom update: sync-bundled-skills \u2014 removed ${r.removed.length} retired ` + `bundled skill(s): ${r.removed.join(", ")}.
85529
+ `);
85336
85530
  }
85337
- mkdirSync35(dirname21(dest), { recursive: true });
85338
- cpSync2(source, dest, { recursive: true, dereference: false });
85339
85531
  } catch (err) {
85340
85532
  throw new Error(`sync-bundled-skills failed: ${err.message}`);
85341
85533
  }
85342
85534
  }
85343
85535
  });
85536
+ steps.push({
85537
+ name: "verify-bundled-skills",
85538
+ description: "Assert every builtin default skill is present in ~/.switchroom/skills/_bundled/ after sync.",
85539
+ run: () => {
85540
+ if (opts.syncBundledSkillsFn)
85541
+ return;
85542
+ const dest = join70(homedir40(), ".switchroom", "skills", "_bundled");
85543
+ if (!existsSync68(dest)) {
85544
+ return;
85545
+ }
85546
+ const missing = getBuiltinDefaultSkillEntries().map((e) => e.key).filter((key) => !existsSync68(join70(dest, key)));
85547
+ if (missing.length > 0) {
85548
+ throw new Error(`verify-bundled-skills: builtin default skill(s) missing from the pool after sync: ` + `${missing.join(", ")}. These ship in the CLI package and must exist in ${dest}. ` + `This is a broken sync or a packaging regression \u2014 the pool is not converged.`);
85549
+ }
85550
+ }
85551
+ });
85344
85552
  steps.push({
85345
85553
  name: "stamp-restart-marker",
85346
85554
  description: 'Write a clean-shutdown marker for every agent (reason="operator: switchroom update") so the post-recreate boot card renders as graceful rather than crash',
@@ -85370,7 +85578,7 @@ function planUpdate(opts) {
85370
85578
  description: "docker compose up -d --remove-orphans (recreates services with new images / compose)",
85371
85579
  run: () => {
85372
85580
  try {
85373
- const composeText = readFileSync60(composePath, "utf8");
85581
+ const composeText = readFileSync61(composePath, "utf8");
85374
85582
  const pf = validateBindSources(composeText);
85375
85583
  if (!pf.ok)
85376
85584
  throw new Error(formatPreflightError(pf));
@@ -85447,12 +85655,12 @@ function defaultStatusProbe(composePath) {
85447
85655
  try {
85448
85656
  cliBuiltAt = new Date(statSync40(scriptPath).mtimeMs).toISOString();
85449
85657
  } catch {}
85450
- let dir = dirname21(scriptPath);
85658
+ let dir = dirname23(scriptPath);
85451
85659
  for (let i = 0;i < 8; i++) {
85452
- const pkgPath = join69(dir, "package.json");
85453
- if (existsSync67(pkgPath)) {
85660
+ const pkgPath = join70(dir, "package.json");
85661
+ if (existsSync68(pkgPath)) {
85454
85662
  try {
85455
- const pkg = JSON.parse(readFileSync60(pkgPath, "utf-8"));
85663
+ const pkg = JSON.parse(readFileSync61(pkgPath, "utf-8"));
85456
85664
  if (typeof pkg.version === "string")
85457
85665
  cliVersion = pkg.version;
85458
85666
  } catch (err) {
@@ -85460,7 +85668,7 @@ function defaultStatusProbe(composePath) {
85460
85668
  }
85461
85669
  break;
85462
85670
  }
85463
- const parent = dirname21(dir);
85671
+ const parent = dirname23(dir);
85464
85672
  if (parent === dir)
85465
85673
  break;
85466
85674
  dir = parent;
@@ -85473,7 +85681,7 @@ function defaultStatusProbe(composePath) {
85473
85681
  warnings.push("could not resolve CLI version (no package.json found above the resolved script path)");
85474
85682
  }
85475
85683
  const services = [];
85476
- if (!existsSync67(composePath)) {
85684
+ if (!existsSync68(composePath)) {
85477
85685
  warnings.push(`compose file not found at ${composePath}; service status unknown`);
85478
85686
  return { cliVersion, cliBuiltAt, services, warnings };
85479
85687
  }
@@ -85669,7 +85877,7 @@ function registerUpdateCommand(program3) {
85669
85877
  // src/cli/rollout.ts
85670
85878
  init_helpers();
85671
85879
  import { spawnSync as spawnSync14 } from "node:child_process";
85672
- import { readFileSync as readFileSync61, chownSync as chownSync6, statSync as statSync41 } from "node:fs";
85880
+ import { readFileSync as readFileSync62, chownSync as chownSync6, statSync as statSync41 } from "node:fs";
85673
85881
  import { homedir as homedir41 } from "node:os";
85674
85882
  init_operator_uid();
85675
85883
  init_atomic();
@@ -85955,7 +86163,7 @@ function resolveRollbackTarget(auditLogPath) {
85955
86163
  const logPath = auditLogPath ?? defaultAuditLogPath2(homedir41());
85956
86164
  let raw;
85957
86165
  try {
85958
- raw = readFileSync61(logPath, "utf8");
86166
+ raw = readFileSync62(logPath, "utf8");
85959
86167
  } catch {
85960
86168
  return null;
85961
86169
  }
@@ -86073,7 +86281,7 @@ function registerRolloutCommand(program3) {
86073
86281
  `),
86074
86282
  webImageTag: () => deployedImageTag("switchroom-web"),
86075
86283
  persistPin: (pin) => {
86076
- const before = readFileSync61(configPath, "utf8");
86284
+ const before = readFileSync62(configPath, "utf8");
86077
86285
  const after = setReleasePinInConfig(before, pin);
86078
86286
  if (after === before)
86079
86287
  return;
@@ -86151,8 +86359,8 @@ init_helpers();
86151
86359
  init_lifecycle();
86152
86360
  init_resolve_version();
86153
86361
  import { execSync as execSync3 } from "node:child_process";
86154
- import { existsSync as existsSync68, readFileSync as readFileSync62 } from "node:fs";
86155
- import { dirname as dirname22, join as join70 } from "node:path";
86362
+ import { existsSync as existsSync69, readFileSync as readFileSync63 } from "node:fs";
86363
+ import { dirname as dirname24, join as join71 } from "node:path";
86156
86364
  function getClaudeCodeVersion() {
86157
86365
  try {
86158
86366
  const out = execSync3("claude --version 2>/dev/null", {
@@ -86202,16 +86410,16 @@ function formatUptime3(timestamp) {
86202
86410
  function locateSwitchroomInstallDir() {
86203
86411
  let dir = import.meta.dirname;
86204
86412
  for (let i = 0;i < 10 && dir && dir !== "/"; i++) {
86205
- const pkgPath = join70(dir, "package.json");
86206
- if (existsSync68(pkgPath)) {
86413
+ const pkgPath = join71(dir, "package.json");
86414
+ if (existsSync69(pkgPath)) {
86207
86415
  try {
86208
- const pkg = JSON.parse(readFileSync62(pkgPath, "utf-8"));
86209
- if (pkg.name === "switchroom" && existsSync68(join70(dir, ".git"))) {
86416
+ const pkg = JSON.parse(readFileSync63(pkgPath, "utf-8"));
86417
+ if (pkg.name === "switchroom" && existsSync69(join71(dir, ".git"))) {
86210
86418
  return dir;
86211
86419
  }
86212
86420
  } catch {}
86213
86421
  }
86214
- dir = dirname22(dir);
86422
+ dir = dirname24(dir);
86215
86423
  }
86216
86424
  return null;
86217
86425
  }
@@ -86384,29 +86592,29 @@ import { resolve as resolve42 } from "node:path";
86384
86592
 
86385
86593
  // src/agents/session-retention.ts
86386
86594
  import {
86387
- existsSync as existsSync69,
86388
- readdirSync as readdirSync24,
86595
+ existsSync as existsSync70,
86596
+ readdirSync as readdirSync25,
86389
86597
  statSync as statSync42,
86390
86598
  unlinkSync as unlinkSync14
86391
86599
  } from "node:fs";
86392
- import { join as join71 } from "node:path";
86600
+ import { join as join72 } from "node:path";
86393
86601
  var DEFAULT_SESSION_RETENTION_MAX_COUNT = 20;
86394
86602
  var DEFAULT_SESSION_RETENTION_MAX_AGE_DAYS = 30;
86395
86603
  var MIN_KEEP = 2;
86396
86604
  function collectSessionJsonl(claudeConfigDir) {
86397
- const projects = join71(claudeConfigDir, "projects");
86398
- if (!existsSync69(projects))
86605
+ const projects = join72(claudeConfigDir, "projects");
86606
+ if (!existsSync70(projects))
86399
86607
  return [];
86400
86608
  const found = [];
86401
86609
  const walk2 = (dir) => {
86402
86610
  let entries;
86403
86611
  try {
86404
- entries = readdirSync24(dir);
86612
+ entries = readdirSync25(dir);
86405
86613
  } catch {
86406
86614
  return;
86407
86615
  }
86408
86616
  for (const name of entries) {
86409
- const full = join71(dir, name);
86617
+ const full = join72(dir, name);
86410
86618
  let st;
86411
86619
  try {
86412
86620
  st = statSync42(full);
@@ -86526,18 +86734,18 @@ function registerHandoffCommand(program3) {
86526
86734
  // src/issues/store.ts
86527
86735
  import {
86528
86736
  closeSync as closeSync12,
86529
- existsSync as existsSync70,
86530
- mkdirSync as mkdirSync36,
86737
+ existsSync as existsSync71,
86738
+ mkdirSync as mkdirSync37,
86531
86739
  openSync as openSync12,
86532
- readdirSync as readdirSync25,
86533
- readFileSync as readFileSync63,
86534
- renameSync as renameSync16,
86740
+ readdirSync as readdirSync26,
86741
+ readFileSync as readFileSync64,
86742
+ renameSync as renameSync17,
86535
86743
  statSync as statSync43,
86536
86744
  unlinkSync as unlinkSync15,
86537
- writeFileSync as writeFileSync19,
86745
+ writeFileSync as writeFileSync20,
86538
86746
  writeSync as writeSync9
86539
86747
  } from "node:fs";
86540
- import { join as join72 } from "node:path";
86748
+ import { join as join73 } from "node:path";
86541
86749
  import { randomBytes as randomBytes12 } from "node:crypto";
86542
86750
  import { execSync as execSync4 } from "node:child_process";
86543
86751
 
@@ -86968,12 +87176,12 @@ function redactedMarker(ruleId) {
86968
87176
  var ISSUES_FILE = "issues.jsonl";
86969
87177
  var ISSUES_LOCK = "issues.lock";
86970
87178
  function readAll(stateDir) {
86971
- const path5 = join72(stateDir, ISSUES_FILE);
86972
- if (!existsSync70(path5))
87179
+ const path5 = join73(stateDir, ISSUES_FILE);
87180
+ if (!existsSync71(path5))
86973
87181
  return [];
86974
87182
  let raw;
86975
87183
  try {
86976
- raw = readFileSync63(path5, "utf-8");
87184
+ raw = readFileSync64(path5, "utf-8");
86977
87185
  } catch {
86978
87186
  return [];
86979
87187
  }
@@ -87046,7 +87254,7 @@ function record(stateDir, input, nowFn = Date.now) {
87046
87254
  });
87047
87255
  }
87048
87256
  function resolve43(stateDir, fingerprint, nowFn = Date.now) {
87049
- if (!existsSync70(join72(stateDir, ISSUES_FILE)))
87257
+ if (!existsSync71(join73(stateDir, ISSUES_FILE)))
87050
87258
  return 0;
87051
87259
  return withLock(stateDir, () => {
87052
87260
  const all = readAll(stateDir);
@@ -87064,7 +87272,7 @@ function resolve43(stateDir, fingerprint, nowFn = Date.now) {
87064
87272
  });
87065
87273
  }
87066
87274
  function resolveAllBySource(stateDir, source, nowFn = Date.now) {
87067
- if (!existsSync70(join72(stateDir, ISSUES_FILE)))
87275
+ if (!existsSync71(join73(stateDir, ISSUES_FILE)))
87068
87276
  return 0;
87069
87277
  return withLock(stateDir, () => {
87070
87278
  const all = readAll(stateDir);
@@ -87082,7 +87290,7 @@ function resolveAllBySource(stateDir, source, nowFn = Date.now) {
87082
87290
  });
87083
87291
  }
87084
87292
  function prune(stateDir, opts = {}) {
87085
- if (!existsSync70(join72(stateDir, ISSUES_FILE)))
87293
+ if (!existsSync71(join73(stateDir, ISSUES_FILE)))
87086
87294
  return 0;
87087
87295
  return withLock(stateDir, () => {
87088
87296
  const all = readAll(stateDir);
@@ -87112,24 +87320,24 @@ function prune(stateDir, opts = {}) {
87112
87320
  });
87113
87321
  }
87114
87322
  function ensureDir(stateDir) {
87115
- mkdirSync36(stateDir, { recursive: true });
87323
+ mkdirSync37(stateDir, { recursive: true });
87116
87324
  }
87117
87325
  function writeAll(stateDir, events) {
87118
- const path5 = join72(stateDir, ISSUES_FILE);
87326
+ const path5 = join73(stateDir, ISSUES_FILE);
87119
87327
  sweepOrphanTmpFiles(stateDir);
87120
87328
  const tmp = `${path5}.tmp-${process.pid}-${randomBytes12(4).toString("hex")}`;
87121
87329
  const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
87122
87330
  `) + `
87123
87331
  `;
87124
- writeFileSync19(tmp, body, "utf-8");
87125
- renameSync16(tmp, path5);
87332
+ writeFileSync20(tmp, body, "utf-8");
87333
+ renameSync17(tmp, path5);
87126
87334
  }
87127
87335
  var ORPHAN_TMP_TTL_MS = 60000;
87128
87336
  var TMP_PREFIX = `${ISSUES_FILE}.tmp-`;
87129
87337
  function sweepOrphanTmpFiles(stateDir) {
87130
87338
  let entries;
87131
87339
  try {
87132
- entries = readdirSync25(stateDir);
87340
+ entries = readdirSync26(stateDir);
87133
87341
  } catch {
87134
87342
  return;
87135
87343
  }
@@ -87137,7 +87345,7 @@ function sweepOrphanTmpFiles(stateDir) {
87137
87345
  for (const entry of entries) {
87138
87346
  if (!entry.startsWith(TMP_PREFIX))
87139
87347
  continue;
87140
- const tmpPath = join72(stateDir, entry);
87348
+ const tmpPath = join73(stateDir, entry);
87141
87349
  try {
87142
87350
  const stat = statSync43(tmpPath);
87143
87351
  if (stat.mtimeMs < cutoff) {
@@ -87149,7 +87357,7 @@ function sweepOrphanTmpFiles(stateDir) {
87149
87357
  var LOCK_RETRY_MS = 25;
87150
87358
  var LOCK_TIMEOUT_MS = 1e4;
87151
87359
  function withLock(stateDir, fn) {
87152
- const lockPath = join72(stateDir, ISSUES_LOCK);
87360
+ const lockPath = join73(stateDir, ISSUES_LOCK);
87153
87361
  const startedAt = Date.now();
87154
87362
  let fd = null;
87155
87363
  while (fd === null) {
@@ -87184,7 +87392,7 @@ function withLock(stateDir, fn) {
87184
87392
  function tryStealStaleLock(lockPath) {
87185
87393
  let pidStr;
87186
87394
  try {
87187
- pidStr = readFileSync63(lockPath, "utf-8").trim();
87395
+ pidStr = readFileSync64(lockPath, "utf-8").trim();
87188
87396
  } catch {
87189
87397
  return true;
87190
87398
  }
@@ -87432,20 +87640,20 @@ function relTime(deltaMs) {
87432
87640
 
87433
87641
  // src/cli/deps.ts
87434
87642
  init_source();
87435
- import { existsSync as existsSync73 } from "node:fs";
87643
+ import { existsSync as existsSync74 } from "node:fs";
87436
87644
  import { homedir as homedir44 } from "node:os";
87437
- import { join as join75, resolve as resolve44 } from "node:path";
87645
+ import { join as join76, resolve as resolve44 } from "node:path";
87438
87646
 
87439
87647
  // src/deps/python.ts
87440
87648
  import { createHash as createHash13 } from "node:crypto";
87441
87649
  import {
87442
- existsSync as existsSync71,
87443
- mkdirSync as mkdirSync37,
87444
- readFileSync as readFileSync64,
87650
+ existsSync as existsSync72,
87651
+ mkdirSync as mkdirSync38,
87652
+ readFileSync as readFileSync65,
87445
87653
  rmSync as rmSync13,
87446
- writeFileSync as writeFileSync20
87654
+ writeFileSync as writeFileSync21
87447
87655
  } from "node:fs";
87448
- import { dirname as dirname23, join as join73 } from "node:path";
87656
+ import { dirname as dirname25, join as join74 } from "node:path";
87449
87657
  import { homedir as homedir42 } from "node:os";
87450
87658
  import { execFileSync as execFileSync21 } from "node:child_process";
87451
87659
 
@@ -87458,26 +87666,26 @@ class PythonEnvError extends Error {
87458
87666
  }
87459
87667
  }
87460
87668
  function defaultPythonCacheRoot() {
87461
- return join73(homedir42(), ".switchroom", "deps", "python");
87669
+ return join74(homedir42(), ".switchroom", "deps", "python");
87462
87670
  }
87463
87671
  function hashFile(path5) {
87464
- return createHash13("sha256").update(readFileSync64(path5)).digest("hex");
87672
+ return createHash13("sha256").update(readFileSync65(path5)).digest("hex");
87465
87673
  }
87466
87674
  function ensurePythonEnv(opts) {
87467
87675
  const { skillName, requirementsPath, force = false } = opts;
87468
87676
  const cacheRoot = opts.cacheRoot ?? defaultPythonCacheRoot();
87469
87677
  const hostPython = opts.pythonBin ?? "python3";
87470
- if (!existsSync71(requirementsPath)) {
87678
+ if (!existsSync72(requirementsPath)) {
87471
87679
  throw new PythonEnvError(`requirements file not found: ${requirementsPath}`);
87472
87680
  }
87473
- const venvDir = join73(cacheRoot, skillName);
87474
- const stampPath = join73(venvDir, ".requirements.sha256");
87475
- const binDir = join73(venvDir, "bin");
87476
- const pythonBin = join73(binDir, "python");
87477
- const pipBin = join73(binDir, "pip");
87681
+ const venvDir = join74(cacheRoot, skillName);
87682
+ const stampPath = join74(venvDir, ".requirements.sha256");
87683
+ const binDir = join74(venvDir, "bin");
87684
+ const pythonBin = join74(binDir, "python");
87685
+ const pipBin = join74(binDir, "pip");
87478
87686
  const targetHash = hashFile(requirementsPath);
87479
- if (!force && existsSync71(stampPath) && existsSync71(pythonBin)) {
87480
- const existingHash = readFileSync64(stampPath, "utf8").trim();
87687
+ if (!force && existsSync72(stampPath) && existsSync72(pythonBin)) {
87688
+ const existingHash = readFileSync65(stampPath, "utf8").trim();
87481
87689
  if (existingHash === targetHash) {
87482
87690
  return {
87483
87691
  skillName,
@@ -87489,10 +87697,10 @@ function ensurePythonEnv(opts) {
87489
87697
  };
87490
87698
  }
87491
87699
  }
87492
- if (existsSync71(venvDir)) {
87700
+ if (existsSync72(venvDir)) {
87493
87701
  rmSync13(venvDir, { recursive: true, force: true });
87494
87702
  }
87495
- mkdirSync37(dirname23(venvDir), { recursive: true });
87703
+ mkdirSync38(dirname25(venvDir), { recursive: true });
87496
87704
  try {
87497
87705
  execFileSync21(hostPython, ["-m", "venv", venvDir], { stdio: "pipe" });
87498
87706
  } catch (err) {
@@ -87511,7 +87719,7 @@ function ensurePythonEnv(opts) {
87511
87719
  const e = err;
87512
87720
  throw new PythonEnvError(`Failed to install requirements for skill "${skillName}": ${e.message}`, e.stderr?.toString());
87513
87721
  }
87514
- writeFileSync20(stampPath, targetHash + `
87722
+ writeFileSync21(stampPath, targetHash + `
87515
87723
  `);
87516
87724
  return {
87517
87725
  skillName,
@@ -87527,13 +87735,13 @@ function ensurePythonEnv(opts) {
87527
87735
  import { createHash as createHash14 } from "node:crypto";
87528
87736
  import {
87529
87737
  copyFileSync as copyFileSync10,
87530
- existsSync as existsSync72,
87531
- mkdirSync as mkdirSync38,
87532
- readFileSync as readFileSync65,
87738
+ existsSync as existsSync73,
87739
+ mkdirSync as mkdirSync39,
87740
+ readFileSync as readFileSync66,
87533
87741
  rmSync as rmSync14,
87534
- writeFileSync as writeFileSync21
87742
+ writeFileSync as writeFileSync22
87535
87743
  } from "node:fs";
87536
- import { dirname as dirname24, join as join74 } from "node:path";
87744
+ import { dirname as dirname26, join as join75 } from "node:path";
87537
87745
  import { homedir as homedir43 } from "node:os";
87538
87746
  import { execFileSync as execFileSync22 } from "node:child_process";
87539
87747
 
@@ -87557,23 +87765,23 @@ var LOCKFILES_FOR = {
87557
87765
  npm: ["package-lock.json"]
87558
87766
  };
87559
87767
  function defaultNodeCacheRoot() {
87560
- return join74(homedir43(), ".switchroom", "deps", "node");
87768
+ return join75(homedir43(), ".switchroom", "deps", "node");
87561
87769
  }
87562
87770
  function hashDepInputs(packageJsonPath) {
87563
- const sourceDir = dirname24(packageJsonPath);
87771
+ const sourceDir = dirname26(packageJsonPath);
87564
87772
  const hasher = createHash14("sha256");
87565
87773
  hasher.update(`package.json
87566
87774
  `);
87567
- hasher.update(readFileSync65(packageJsonPath));
87775
+ hasher.update(readFileSync66(packageJsonPath));
87568
87776
  for (const lockName of ALL_LOCKFILES) {
87569
- const lockPath = join74(sourceDir, lockName);
87570
- if (existsSync72(lockPath)) {
87777
+ const lockPath = join75(sourceDir, lockName);
87778
+ if (existsSync73(lockPath)) {
87571
87779
  hasher.update(`
87572
87780
  `);
87573
87781
  hasher.update(lockName);
87574
87782
  hasher.update(`
87575
87783
  `);
87576
- hasher.update(readFileSync65(lockPath));
87784
+ hasher.update(readFileSync66(lockPath));
87577
87785
  }
87578
87786
  }
87579
87787
  return hasher.digest("hex");
@@ -87582,17 +87790,17 @@ function ensureNodeEnv(opts) {
87582
87790
  const { skillName, packageJsonPath, force = false } = opts;
87583
87791
  const cacheRoot = opts.cacheRoot ?? defaultNodeCacheRoot();
87584
87792
  const installer = opts.installer ?? "bun";
87585
- if (!existsSync72(packageJsonPath)) {
87793
+ if (!existsSync73(packageJsonPath)) {
87586
87794
  throw new NodeEnvError(`package.json not found: ${packageJsonPath}`);
87587
87795
  }
87588
- const sourceDir = dirname24(packageJsonPath);
87589
- const envDir = join74(cacheRoot, skillName);
87590
- const stampPath = join74(envDir, ".package.sha256");
87591
- const nodeModulesDir = join74(envDir, "node_modules");
87592
- const binDir = join74(nodeModulesDir, ".bin");
87796
+ const sourceDir = dirname26(packageJsonPath);
87797
+ const envDir = join75(cacheRoot, skillName);
87798
+ const stampPath = join75(envDir, ".package.sha256");
87799
+ const nodeModulesDir = join75(envDir, "node_modules");
87800
+ const binDir = join75(nodeModulesDir, ".bin");
87593
87801
  const targetHash = hashDepInputs(packageJsonPath);
87594
- if (!force && existsSync72(stampPath) && existsSync72(nodeModulesDir)) {
87595
- const existingHash = readFileSync65(stampPath, "utf8").trim();
87802
+ if (!force && existsSync73(stampPath) && existsSync73(nodeModulesDir)) {
87803
+ const existingHash = readFileSync66(stampPath, "utf8").trim();
87596
87804
  if (existingHash === targetHash) {
87597
87805
  return {
87598
87806
  skillName,
@@ -87603,16 +87811,16 @@ function ensureNodeEnv(opts) {
87603
87811
  };
87604
87812
  }
87605
87813
  }
87606
- if (existsSync72(envDir)) {
87814
+ if (existsSync73(envDir)) {
87607
87815
  rmSync14(envDir, { recursive: true, force: true });
87608
87816
  }
87609
- mkdirSync38(envDir, { recursive: true });
87610
- copyFileSync10(packageJsonPath, join74(envDir, "package.json"));
87817
+ mkdirSync39(envDir, { recursive: true });
87818
+ copyFileSync10(packageJsonPath, join75(envDir, "package.json"));
87611
87819
  let copiedLockfile = false;
87612
87820
  for (const lockName of LOCKFILES_FOR[installer]) {
87613
- const lockPath = join74(sourceDir, lockName);
87614
- if (existsSync72(lockPath)) {
87615
- copyFileSync10(lockPath, join74(envDir, lockName));
87821
+ const lockPath = join75(sourceDir, lockName);
87822
+ if (existsSync73(lockPath)) {
87823
+ copyFileSync10(lockPath, join75(envDir, lockName));
87616
87824
  copiedLockfile = true;
87617
87825
  }
87618
87826
  }
@@ -87628,7 +87836,7 @@ function ensureNodeEnv(opts) {
87628
87836
  const e = err;
87629
87837
  throw new NodeEnvError(`Failed to install node deps for skill "${skillName}" with ${installer}: ${e.message}`, e.stderr?.toString());
87630
87838
  }
87631
- writeFileSync21(stampPath, targetHash + `
87839
+ writeFileSync22(stampPath, targetHash + `
87632
87840
  `);
87633
87841
  return {
87634
87842
  skillName,
@@ -87647,22 +87855,22 @@ function registerDepsCommand(program3) {
87647
87855
  const deps = program3.command("deps").description("Manage cached per-skill dependency environments");
87648
87856
  deps.command("rebuild <skill>").description("Rebuild the Python venv and/or Node node_modules cache for a skill").option("-p, --python", "Rebuild only the Python env").option("-n, --node", "Rebuild only the Node env").action(async (skill, opts) => {
87649
87857
  const skillsRoot = builtinSkillsRoot();
87650
- if (!existsSync73(skillsRoot)) {
87858
+ if (!existsSync74(skillsRoot)) {
87651
87859
  console.error(source_default.red(`Bundled skills pool dir not found at ${skillsRoot} \u2014 run \`switchroom update\` to install it.`));
87652
87860
  process.exit(1);
87653
87861
  }
87654
- const skillDir = join75(skillsRoot, skill);
87655
- if (!existsSync73(skillDir)) {
87862
+ const skillDir = join76(skillsRoot, skill);
87863
+ if (!existsSync74(skillDir)) {
87656
87864
  console.error(source_default.red(`Unknown skill: ${skill} (no dir at ${skillDir})`));
87657
87865
  process.exit(1);
87658
87866
  }
87659
- const requirementsPath = join75(skillDir, "requirements.txt");
87660
- const packageJsonPath = join75(skillDir, "package.json");
87661
- const wantPython = opts.python ?? (!opts.python && !opts.node && existsSync73(requirementsPath));
87662
- const wantNode = opts.node ?? (!opts.python && !opts.node && existsSync73(packageJsonPath));
87867
+ const requirementsPath = join76(skillDir, "requirements.txt");
87868
+ const packageJsonPath = join76(skillDir, "package.json");
87869
+ const wantPython = opts.python ?? (!opts.python && !opts.node && existsSync74(requirementsPath));
87870
+ const wantNode = opts.node ?? (!opts.python && !opts.node && existsSync74(packageJsonPath));
87663
87871
  let did = 0;
87664
87872
  if (wantPython) {
87665
- if (!existsSync73(requirementsPath)) {
87873
+ if (!existsSync74(requirementsPath)) {
87666
87874
  console.error(source_default.red(`Skill "${skill}" has no requirements.txt at ${requirementsPath}`));
87667
87875
  process.exit(1);
87668
87876
  }
@@ -87686,7 +87894,7 @@ function registerDepsCommand(program3) {
87686
87894
  }
87687
87895
  }
87688
87896
  if (wantNode) {
87689
- if (!existsSync73(packageJsonPath)) {
87897
+ if (!existsSync74(packageJsonPath)) {
87690
87898
  console.error(source_default.red(`Skill "${skill}" has no package.json at ${packageJsonPath}`));
87691
87899
  process.exit(1);
87692
87900
  }
@@ -87719,7 +87927,7 @@ function registerDepsCommand(program3) {
87719
87927
  // src/cli/workspace.ts
87720
87928
  init_helpers();
87721
87929
  init_loader();
87722
- import { existsSync as existsSync74 } from "node:fs";
87930
+ import { existsSync as existsSync75 } from "node:fs";
87723
87931
  import { resolve as resolve45, sep as sep3 } from "node:path";
87724
87932
  import { spawnSync as spawnSync15 } from "node:child_process";
87725
87933
 
@@ -88496,7 +88704,7 @@ function registerWorkspaceCommand(program3) {
88496
88704
  if (!dir)
88497
88705
  return;
88498
88706
  const gitDir = resolve45(dir, ".git");
88499
- if (!existsSync74(gitDir)) {
88707
+ if (!existsSync75(gitDir)) {
88500
88708
  process.stdout.write(`Workspace is not a git repository. Re-run \`switchroom agent create ${agentName}\` ` + `or manually \`git init\` in ${dir} to enable versioning.
88501
88709
  `);
88502
88710
  return;
@@ -88550,7 +88758,7 @@ function registerWorkspaceCommand(program3) {
88550
88758
  if (!dir)
88551
88759
  return;
88552
88760
  const gitDir = resolve45(dir, ".git");
88553
- if (!existsSync74(gitDir)) {
88761
+ if (!existsSync75(gitDir)) {
88554
88762
  process.stdout.write(`Workspace is not a git repository.
88555
88763
  `);
88556
88764
  return;
@@ -88575,7 +88783,7 @@ function resolveAgentWorkspaceDirOrExit(program3, agentName) {
88575
88783
  const agentsDir = resolveAgentsDir(config);
88576
88784
  const agentDir = resolve45(agentsDir, agentName);
88577
88785
  const dir = resolveAgentWorkspaceDir(agentDir);
88578
- if (!existsSync74(dir)) {
88786
+ if (!existsSync75(dir)) {
88579
88787
  process.stderr.write(`workspace: ${dir} does not exist yet. Run \`switchroom setup\` or \`switchroom agent scaffold ${agentName}\` to seed it.
88580
88788
  `);
88581
88789
  return;
@@ -88611,8 +88819,8 @@ function safeParseInt(value, fallback) {
88611
88819
  init_helpers();
88612
88820
  init_loader();
88613
88821
  init_merge();
88614
- import { copyFileSync as copyFileSync11, existsSync as existsSync75, readFileSync as readFileSync66, writeFileSync as writeFileSync22 } from "node:fs";
88615
- import { join as join76, resolve as resolve46 } from "node:path";
88822
+ import { copyFileSync as copyFileSync11, existsSync as existsSync76, readFileSync as readFileSync67, writeFileSync as writeFileSync23 } from "node:fs";
88823
+ import { join as join77, resolve as resolve46 } from "node:path";
88616
88824
  init_scaffold();
88617
88825
  init_profiles();
88618
88826
  init_schema();
@@ -88629,7 +88837,7 @@ function resolveSoulTargetOrExit(program3, agentName) {
88629
88837
  const agentsDir = resolveAgentsDir(config);
88630
88838
  const agentDir = resolve46(agentsDir, agentName);
88631
88839
  const workspaceDir = resolveAgentWorkspaceDir(agentDir);
88632
- if (!existsSync75(workspaceDir)) {
88840
+ if (!existsSync76(workspaceDir)) {
88633
88841
  console.error(`soul: ${workspaceDir} does not exist yet. Run \`switchroom setup\` ` + `or \`switchroom agent scaffold ${agentName}\` to seed it.`);
88634
88842
  process.exit(1);
88635
88843
  }
@@ -88638,7 +88846,7 @@ function resolveSoulTargetOrExit(program3, agentName) {
88638
88846
  profileName,
88639
88847
  profilePath,
88640
88848
  workspaceDir,
88641
- soulPath: join76(workspaceDir, "SOUL.md"),
88849
+ soulPath: join77(workspaceDir, "SOUL.md"),
88642
88850
  soul: merged.soul
88643
88851
  };
88644
88852
  }
@@ -88655,11 +88863,11 @@ function registerSoulCommand(program3) {
88655
88863
  const t = resolveSoulTargetOrExit(program3, agentName);
88656
88864
  if (!t)
88657
88865
  return;
88658
- if (!existsSync75(t.soulPath)) {
88866
+ if (!existsSync76(t.soulPath)) {
88659
88867
  console.error(`soul: ${t.soulPath} does not exist yet \u2014 run ` + `\`switchroom soul reset ${agentName}\` to seed it.`);
88660
88868
  process.exit(1);
88661
88869
  }
88662
- process.stdout.write(readFileSync66(t.soulPath, "utf-8"));
88870
+ process.stdout.write(readFileSync67(t.soulPath, "utf-8"));
88663
88871
  }));
88664
88872
  cmd.command("reset <agent>").description("Re-seed SOUL.md from the agent's current profile " + "(backs the existing file up to SOUL.md.bak first)").option("-y, --yes", "Skip the confirmation prompt").action(withConfigError(async (agentName, opts) => {
88665
88873
  const t = resolveSoulTargetOrExit(program3, agentName);
@@ -88670,7 +88878,7 @@ function registerSoulCommand(program3) {
88670
88878
  console.error(`soul: profile "${t.profileName}" ships no SOUL.md.hbs \u2014 ` + `nothing to re-seed from.`);
88671
88879
  process.exit(1);
88672
88880
  }
88673
- const exists = existsSync75(t.soulPath);
88881
+ const exists = existsSync76(t.soulPath);
88674
88882
  if (exists && !opts.yes) {
88675
88883
  if (!isInteractive()) {
88676
88884
  console.error(`soul: ${t.soulPath} already exists. Re-run with --yes to ` + `replace it (the current file is backed up to SOUL.md.bak).`);
@@ -88685,12 +88893,12 @@ function registerSoulCommand(program3) {
88685
88893
  let backupPath;
88686
88894
  if (exists) {
88687
88895
  backupPath = `${t.soulPath}.bak`;
88688
- if (existsSync75(backupPath)) {
88896
+ if (existsSync76(backupPath)) {
88689
88897
  backupPath = `${t.soulPath}.bak.${Date.now()}`;
88690
88898
  }
88691
88899
  copyFileSync11(t.soulPath, backupPath);
88692
88900
  }
88693
- writeFileSync22(t.soulPath, content, "utf-8");
88901
+ writeFileSync23(t.soulPath, content, "utf-8");
88694
88902
  if (backupPath) {
88695
88903
  console.log(`soul: re-seeded ${agentName}'s SOUL.md from profile ` + `"${t.profileName}".
88696
88904
  ` + ` Previous version saved to ${backupPath}`);
@@ -88704,8 +88912,8 @@ function registerSoulCommand(program3) {
88704
88912
  // src/cli/debug.ts
88705
88913
  init_helpers();
88706
88914
  init_loader();
88707
- import { existsSync as existsSync76, readFileSync as readFileSync67, readdirSync as readdirSync26, statSync as statSync44 } from "node:fs";
88708
- import { resolve as resolve47, join as join77 } from "node:path";
88915
+ import { existsSync as existsSync77, readFileSync as readFileSync68, readdirSync as readdirSync27, statSync as statSync44 } from "node:fs";
88916
+ import { resolve as resolve47, join as join78 } from "node:path";
88709
88917
  import { createHash as createHash15 } from "node:crypto";
88710
88918
  init_merge();
88711
88919
  init_hindsight2();
@@ -88716,11 +88924,11 @@ function estimateTokens(bytes) {
88716
88924
  return Math.round(bytes / 3.7);
88717
88925
  }
88718
88926
  function readMcpServerNames(agentDir) {
88719
- const mcpPath = join77(agentDir, ".mcp.json");
88720
- if (!existsSync76(mcpPath))
88927
+ const mcpPath = join78(agentDir, ".mcp.json");
88928
+ if (!existsSync77(mcpPath))
88721
88929
  return [];
88722
88930
  try {
88723
- const parsed = JSON.parse(readFileSync67(mcpPath, "utf-8"));
88931
+ const parsed = JSON.parse(readFileSync68(mcpPath, "utf-8"));
88724
88932
  return Object.keys(parsed.mcpServers ?? {});
88725
88933
  } catch {
88726
88934
  return null;
@@ -88730,18 +88938,18 @@ function sha256(content) {
88730
88938
  return createHash15("sha256").update(content).digest("hex").slice(0, 16);
88731
88939
  }
88732
88940
  function findLatestTranscriptJsonl(claudeConfigDir) {
88733
- const projectsDir = join77(claudeConfigDir, "projects");
88734
- if (!existsSync76(projectsDir))
88941
+ const projectsDir = join78(claudeConfigDir, "projects");
88942
+ if (!existsSync77(projectsDir))
88735
88943
  return;
88736
88944
  try {
88737
- const entries = readdirSync26(projectsDir, { withFileTypes: true });
88945
+ const entries = readdirSync27(projectsDir, { withFileTypes: true });
88738
88946
  let latest;
88739
88947
  for (const entry of entries) {
88740
88948
  if (!entry.isDirectory())
88741
88949
  continue;
88742
- const projectPath = join77(projectsDir, entry.name);
88743
- const transcriptPath = join77(projectPath, "transcript.jsonl");
88744
- if (!existsSync76(transcriptPath))
88950
+ const projectPath = join78(projectsDir, entry.name);
88951
+ const transcriptPath = join78(projectPath, "transcript.jsonl");
88952
+ if (!existsSync77(transcriptPath))
88745
88953
  continue;
88746
88954
  const stat3 = statSync44(transcriptPath);
88747
88955
  if (!latest || stat3.mtimeMs > latest.mtime) {
@@ -88755,7 +88963,7 @@ function findLatestTranscriptJsonl(claudeConfigDir) {
88755
88963
  }
88756
88964
  function extractLatestUserMessage(transcriptPath) {
88757
88965
  try {
88758
- const content = readFileSync67(transcriptPath, "utf-8");
88966
+ const content = readFileSync68(transcriptPath, "utf-8");
88759
88967
  const lines = content.trim().split(`
88760
88968
  `).filter(Boolean);
88761
88969
  for (let i = lines.length - 1;i >= 0; i--) {
@@ -88804,16 +89012,16 @@ function registerDebugCommand(program3) {
88804
89012
  }
88805
89013
  const agentsDir = resolveAgentsDir(config);
88806
89014
  const agentDir = resolve47(agentsDir, agentName);
88807
- if (!existsSync76(agentDir)) {
89015
+ if (!existsSync77(agentDir)) {
88808
89016
  console.error(`Agent directory not found: ${agentDir}`);
88809
89017
  process.exit(1);
88810
89018
  }
88811
89019
  const workspaceDir = resolveAgentWorkspaceDir(agentDir);
88812
- const claudeConfigDir = join77(agentDir, ".claude");
88813
- const claudeMdPath = join77(agentDir, "CLAUDE.md");
88814
- const soulMdPath = join77(agentDir, "SOUL.md");
88815
- const workspaceSoulMdPath = join77(workspaceDir, "SOUL.md");
88816
- const handoffPath = join77(agentDir, ".handoff.md");
89020
+ const claudeConfigDir = join78(agentDir, ".claude");
89021
+ const claudeMdPath = join78(agentDir, "CLAUDE.md");
89022
+ const soulMdPath = join78(agentDir, "SOUL.md");
89023
+ const workspaceSoulMdPath = join78(workspaceDir, "SOUL.md");
89024
+ const handoffPath = join78(agentDir, ".handoff.md");
88817
89025
  const lastN = parseInt(opts.last, 10);
88818
89026
  if (isNaN(lastN) || lastN < 1) {
88819
89027
  console.error("--last must be a positive integer");
@@ -88859,7 +89067,7 @@ function registerDebugCommand(program3) {
88859
89067
  }
88860
89068
  console.log(`=== Append System Prompt (per-session) ===
88861
89069
  `);
88862
- const handoffContent = existsSync76(handoffPath) ? readFileSync67(handoffPath, "utf-8") : "";
89070
+ const handoffContent = existsSync77(handoffPath) ? readFileSync68(handoffPath, "utf-8") : "";
88863
89071
  if (handoffContent.trim().length > 0) {
88864
89072
  console.log(`-- Handoff Briefing (${formatBytes(handoffContent.length)}) --`);
88865
89073
  console.log(handoffContent);
@@ -88870,7 +89078,7 @@ function registerDebugCommand(program3) {
88870
89078
  }
88871
89079
  console.log(`=== CLAUDE.md (auto-loaded by Claude Code) ===
88872
89080
  `);
88873
- const claudeMdContent = existsSync76(claudeMdPath) ? readFileSync67(claudeMdPath, "utf-8") : "";
89081
+ const claudeMdContent = existsSync77(claudeMdPath) ? readFileSync68(claudeMdPath, "utf-8") : "";
88874
89082
  if (claudeMdContent.trim().length > 0) {
88875
89083
  console.log(`(${formatBytes(claudeMdContent.length)})`);
88876
89084
  console.log(claudeMdContent);
@@ -88881,7 +89089,7 @@ function registerDebugCommand(program3) {
88881
89089
  }
88882
89090
  console.log(`=== Persona (SOUL.md) ===
88883
89091
  `);
88884
- const soulMdContent = existsSync76(soulMdPath) ? readFileSync67(soulMdPath, "utf-8") : existsSync76(workspaceSoulMdPath) ? readFileSync67(workspaceSoulMdPath, "utf-8") : "";
89092
+ const soulMdContent = existsSync77(soulMdPath) ? readFileSync68(soulMdPath, "utf-8") : existsSync77(workspaceSoulMdPath) ? readFileSync68(workspaceSoulMdPath, "utf-8") : "";
88885
89093
  if (soulMdContent.trim().length > 0) {
88886
89094
  console.log(`(${formatBytes(soulMdContent.length)})`);
88887
89095
  console.log(soulMdContent);
@@ -88942,11 +89150,11 @@ function registerDebugCommand(program3) {
88942
89150
  const soulMdBytes = soulMdContent.length;
88943
89151
  const perTurnBytes = dynamicResult.concatenated.length;
88944
89152
  const userBytes = userMessage?.text.length ?? 0;
88945
- const fleetDir = join77(agentsDir, "..", "fleet");
88946
- const fleetInvPath = join77(fleetDir, "switchroom-invariants.md");
88947
- const fleetClaudePath = join77(fleetDir, "CLAUDE.md");
88948
- const fleetInvBytes = existsSync76(fleetInvPath) ? readFileSync67(fleetInvPath, "utf-8").length : 0;
88949
- const fleetClaudeBytes = existsSync76(fleetClaudePath) ? readFileSync67(fleetClaudePath, "utf-8").length : 0;
89153
+ const fleetDir = join78(agentsDir, "..", "fleet");
89154
+ const fleetInvPath = join78(fleetDir, "switchroom-invariants.md");
89155
+ const fleetClaudePath = join78(fleetDir, "CLAUDE.md");
89156
+ const fleetInvBytes = existsSync77(fleetInvPath) ? readFileSync68(fleetInvPath, "utf-8").length : 0;
89157
+ const fleetClaudeBytes = existsSync77(fleetClaudePath) ? readFileSync68(fleetClaudePath, "utf-8").length : 0;
88950
89158
  const fleetBytes = fleetInvBytes + fleetClaudeBytes;
88951
89159
  const totalBytes = stableBytes + perSessionBytes + claudeMdBytes + fleetBytes + perTurnBytes + userBytes;
88952
89160
  console.log(`Stable prefix: ${formatBytes(stableBytes).padEnd(20)} (cache-hot; includes SOUL.md ${soulMdBytes.toLocaleString()}B)`);
@@ -88979,44 +89187,44 @@ init_source();
88979
89187
 
88980
89188
  // src/worktree/claim.ts
88981
89189
  import { execFileSync as execFileSync23 } from "node:child_process";
88982
- import { closeSync as closeSync13, mkdirSync as mkdirSync40, openSync as openSync13, existsSync as existsSync78, unlinkSync as unlinkSync17 } from "node:fs";
88983
- import { join as join79, resolve as resolve49 } from "node:path";
89190
+ import { closeSync as closeSync13, mkdirSync as mkdirSync41, openSync as openSync13, existsSync as existsSync79, unlinkSync as unlinkSync17 } from "node:fs";
89191
+ import { join as join80, resolve as resolve49 } from "node:path";
88984
89192
  import { homedir as homedir46 } from "node:os";
88985
89193
  import { randomBytes as randomBytes13 } from "node:crypto";
88986
89194
 
88987
89195
  // src/worktree/registry.ts
88988
89196
  import {
88989
- mkdirSync as mkdirSync39,
88990
- writeFileSync as writeFileSync23,
88991
- readFileSync as readFileSync68,
88992
- readdirSync as readdirSync27,
89197
+ mkdirSync as mkdirSync40,
89198
+ writeFileSync as writeFileSync24,
89199
+ readFileSync as readFileSync69,
89200
+ readdirSync as readdirSync28,
88993
89201
  unlinkSync as unlinkSync16,
88994
- existsSync as existsSync77,
88995
- renameSync as renameSync17
89202
+ existsSync as existsSync78,
89203
+ renameSync as renameSync18
88996
89204
  } from "node:fs";
88997
- import { join as join78, resolve as resolve48 } from "node:path";
89205
+ import { join as join79, resolve as resolve48 } from "node:path";
88998
89206
  import { homedir as homedir45 } from "node:os";
88999
89207
  function registryDir() {
89000
- return resolve48(process.env.SWITCHROOM_WORKTREE_DIR ?? join78(homedir45(), ".switchroom", "worktrees"));
89208
+ return resolve48(process.env.SWITCHROOM_WORKTREE_DIR ?? join79(homedir45(), ".switchroom", "worktrees"));
89001
89209
  }
89002
89210
  function recordPath(id) {
89003
- return join78(registryDir(), `${id}.json`);
89211
+ return join79(registryDir(), `${id}.json`);
89004
89212
  }
89005
89213
  function ensureDir2() {
89006
- mkdirSync39(registryDir(), { recursive: true });
89214
+ mkdirSync40(registryDir(), { recursive: true });
89007
89215
  }
89008
89216
  function writeRecord(record2) {
89009
89217
  ensureDir2();
89010
89218
  const target = recordPath(record2.id);
89011
89219
  const tmp = `${target}.tmp${process.pid}`;
89012
- writeFileSync23(tmp, JSON.stringify(record2, null, 2) + `
89220
+ writeFileSync24(tmp, JSON.stringify(record2, null, 2) + `
89013
89221
  `, { mode: 384 });
89014
- renameSync17(tmp, target);
89222
+ renameSync18(tmp, target);
89015
89223
  }
89016
89224
  function readRecord(id) {
89017
89225
  const path8 = recordPath(id);
89018
89226
  try {
89019
- const raw = readFileSync68(path8, "utf8");
89227
+ const raw = readFileSync69(path8, "utf8");
89020
89228
  return JSON.parse(raw);
89021
89229
  } catch {
89022
89230
  return null;
@@ -89032,7 +89240,7 @@ function listRecords() {
89032
89240
  ensureDir2();
89033
89241
  const dir = registryDir();
89034
89242
  const records = [];
89035
- for (const entry of readdirSync27(dir)) {
89243
+ for (const entry of readdirSync28(dir)) {
89036
89244
  if (!entry.endsWith(".json"))
89037
89245
  continue;
89038
89246
  const id = entry.slice(0, -5);
@@ -89049,9 +89257,9 @@ function countByRepo(repoPath) {
89049
89257
  // src/worktree/claim.ts
89050
89258
  function acquireRepoLock(repoPath) {
89051
89259
  const lockDir = registryDir();
89052
- mkdirSync40(lockDir, { recursive: true });
89260
+ mkdirSync41(lockDir, { recursive: true });
89053
89261
  const lockName = repoPath.replace(/[^A-Za-z0-9]/g, "_");
89054
- const lockPath = join79(lockDir, `.lock-${lockName}`);
89262
+ const lockPath = join80(lockDir, `.lock-${lockName}`);
89055
89263
  const deadline = Date.now() + 5000;
89056
89264
  let fd = null;
89057
89265
  while (fd === null) {
@@ -89078,7 +89286,7 @@ function acquireRepoLock(repoPath) {
89078
89286
  }
89079
89287
  var DEFAULT_CONCURRENCY = 5;
89080
89288
  function worktreesBaseDir() {
89081
- return resolve49(process.env.SWITCHROOM_WORKTREE_BASE ?? join79(homedir46(), ".switchroom", "worktree-checkouts"));
89289
+ return resolve49(process.env.SWITCHROOM_WORKTREE_BASE ?? join80(homedir46(), ".switchroom", "worktree-checkouts"));
89082
89290
  }
89083
89291
  function shortId() {
89084
89292
  return randomBytes13(4).toString("hex");
@@ -89100,12 +89308,12 @@ function resolveRepoPath(repo, codeRepos) {
89100
89308
  }
89101
89309
  function expandHome(p) {
89102
89310
  if (p.startsWith("~/"))
89103
- return join79(homedir46(), p.slice(2));
89311
+ return join80(homedir46(), p.slice(2));
89104
89312
  return p;
89105
89313
  }
89106
89314
  async function claimWorktree(input, codeRepos) {
89107
89315
  const repoPath = resolveRepoPath(input.repo, codeRepos);
89108
- if (!existsSync78(repoPath)) {
89316
+ if (!existsSync79(repoPath)) {
89109
89317
  throw new Error(`Repository path does not exist: ${repoPath}`);
89110
89318
  }
89111
89319
  let concurrencyCap = DEFAULT_CONCURRENCY;
@@ -89127,8 +89335,8 @@ async function claimWorktree(input, codeRepos) {
89127
89335
  const taskSuffix = input.taskName ? sanitizeTaskName(input.taskName) : "task";
89128
89336
  branch = `task/${taskSuffix}-${id}`;
89129
89337
  const baseDir = worktreesBaseDir();
89130
- mkdirSync40(baseDir, { recursive: true });
89131
- worktreePath = join79(baseDir, `${id}-${taskSuffix}`);
89338
+ mkdirSync41(baseDir, { recursive: true });
89339
+ worktreePath = join80(baseDir, `${id}-${taskSuffix}`);
89132
89340
  const ambientOwner = process.env.SWITCHROOM_AGENT_NAME;
89133
89341
  const ownerAgent = input.ownerAgent ?? (ambientOwner != null && ambientOwner !== "" ? ambientOwner : undefined);
89134
89342
  const now = new Date().toISOString();
@@ -89161,7 +89369,7 @@ async function claimWorktree(input, codeRepos) {
89161
89369
 
89162
89370
  // src/worktree/release.ts
89163
89371
  import { execFileSync as execFileSync24 } from "node:child_process";
89164
- import { existsSync as existsSync79 } from "node:fs";
89372
+ import { existsSync as existsSync80 } from "node:fs";
89165
89373
  function releaseWorktree(input) {
89166
89374
  const { id } = input;
89167
89375
  const record2 = readRecord(id);
@@ -89169,7 +89377,7 @@ function releaseWorktree(input) {
89169
89377
  return { released: true };
89170
89378
  }
89171
89379
  let gitSuccess = true;
89172
- if (existsSync79(record2.path)) {
89380
+ if (existsSync80(record2.path)) {
89173
89381
  try {
89174
89382
  execFileSync24("git", ["worktree", "remove", "--force", record2.path], {
89175
89383
  cwd: record2.repo,
@@ -89208,7 +89416,7 @@ function listWorktrees() {
89208
89416
 
89209
89417
  // src/worktree/reaper.ts
89210
89418
  import { execFileSync as execFileSync25 } from "node:child_process";
89211
- import { existsSync as existsSync80 } from "node:fs";
89419
+ import { existsSync as existsSync81 } from "node:fs";
89212
89420
  var STALE_THRESHOLD_MS = 10 * 60 * 1000;
89213
89421
  function reapSkipReasonText(action) {
89214
89422
  switch (action) {
@@ -89269,7 +89477,7 @@ function planReaper(nowMs, deps = {}) {
89269
89477
  const plan = [];
89270
89478
  for (const record2 of listRecords()) {
89271
89479
  const heartbeatAge = now - new Date(record2.heartbeatAt).getTime();
89272
- const worktreeExists = existsSync80(record2.path);
89480
+ const worktreeExists = existsSync81(record2.path);
89273
89481
  if (!worktreeExists) {
89274
89482
  plan.push({
89275
89483
  record: record2,
@@ -89350,16 +89558,16 @@ function runReaper(nowMs, deps = {}) {
89350
89558
  // src/worktree/gc.ts
89351
89559
  import { execFileSync as execFileSync26 } from "node:child_process";
89352
89560
  import {
89353
- existsSync as existsSync81,
89354
- readFileSync as readFileSync69,
89355
- readdirSync as readdirSync28,
89561
+ existsSync as existsSync82,
89562
+ readFileSync as readFileSync70,
89563
+ readdirSync as readdirSync29,
89356
89564
  statSync as statSync45,
89357
- renameSync as renameSync18,
89358
- mkdirSync as mkdirSync41,
89565
+ renameSync as renameSync19,
89566
+ mkdirSync as mkdirSync42,
89359
89567
  rmSync as rmSync15
89360
89568
  } from "node:fs";
89361
89569
  import { homedir as homedir47 } from "node:os";
89362
- import { join as join80, resolve as resolve50 } from "node:path";
89570
+ import { join as join81, resolve as resolve50 } from "node:path";
89363
89571
  function parseGitdirPointer(dotGitFileContents) {
89364
89572
  const m = /^gitdir:\s*(.+?)\s*$/m.exec(dotGitFileContents);
89365
89573
  return m ? m[1] : null;
@@ -89474,17 +89682,17 @@ function defaultPrSignal(repo, branch, exec) {
89474
89682
  }
89475
89683
  }
89476
89684
  function trashRoot() {
89477
- return resolve50(process.env.SWITCHROOM_WORKTREE_TRASH ?? join80(homedir47(), ".switchroom", "worktree-gc-trash"));
89685
+ return resolve50(process.env.SWITCHROOM_WORKTREE_TRASH ?? join81(homedir47(), ".switchroom", "worktree-gc-trash"));
89478
89686
  }
89479
89687
  function planGc(roots, deps = {}) {
89480
- const exists = deps.existsSync ?? existsSync81;
89481
- const readDir = deps.readDir ?? ((p) => readdirSync28(p));
89482
- const readFile4 = deps.readFile ?? ((p) => readFileSync69(p, "utf8"));
89688
+ const exists = deps.existsSync ?? existsSync82;
89689
+ const readDir = deps.readDir ?? ((p) => readdirSync29(p));
89690
+ const readFile4 = deps.readFile ?? ((p) => readFileSync70(p, "utf8"));
89483
89691
  const stat3 = deps.stat ?? ((p) => statSync45(p));
89484
89692
  const exec = deps.exec ?? defaultExec;
89485
89693
  const prSignal = deps.prSignal ?? ((repo, branch) => defaultPrSignal(repo, branch, exec));
89486
89694
  const stamp = deps.dateStamp ?? "undated";
89487
- const trash = join80(trashRoot(), stamp);
89695
+ const trash = join81(trashRoot(), stamp);
89488
89696
  let claimed;
89489
89697
  try {
89490
89698
  claimed = new Set(listRecords().map((r) => resolve50(r.path)));
@@ -89520,10 +89728,10 @@ function planGc(roots, deps = {}) {
89520
89728
  continue;
89521
89729
  }
89522
89730
  for (const name of entries) {
89523
- const dir = join80(root, name);
89731
+ const dir = join81(root, name);
89524
89732
  if (isEphemeralPath(dir))
89525
89733
  continue;
89526
- const dotGit = join80(dir, ".git");
89734
+ const dotGit = join81(dir, ".git");
89527
89735
  if (!exists(dotGit))
89528
89736
  continue;
89529
89737
  let st;
@@ -89552,7 +89760,7 @@ function planGc(roots, deps = {}) {
89552
89760
  ownerRepos.add(repoRoot);
89553
89761
  if (exists(ptr))
89554
89762
  continue;
89555
- orphans.push({ dir, owner: repoRoot, dest: join80(trash, name) });
89763
+ orphans.push({ dir, owner: repoRoot, dest: join81(trash, name) });
89556
89764
  }
89557
89765
  }
89558
89766
  const registered = [];
@@ -89607,10 +89815,10 @@ function planGc(roots, deps = {}) {
89607
89815
  }
89608
89816
  function applyGc(plan, deps = {}) {
89609
89817
  const exec = deps.exec ?? defaultExec;
89610
- const mkdirp = deps.mkdirp ?? ((p) => void mkdirSync41(p, { recursive: true }));
89818
+ const mkdirp = deps.mkdirp ?? ((p) => void mkdirSync42(p, { recursive: true }));
89611
89819
  const move = deps.move ?? ((src, dest) => {
89612
89820
  try {
89613
- renameSync18(src, dest);
89821
+ renameSync19(src, dest);
89614
89822
  } catch {
89615
89823
  exec("mv", [src, dest]);
89616
89824
  }
@@ -89656,14 +89864,14 @@ function selectPurgeTargets(entries, olderThanDays) {
89656
89864
  return entries.filter((e) => e.ageDays >= olderThanDays).map((e) => e.path);
89657
89865
  }
89658
89866
  function listTrashEntries(nowMs, deps = {}) {
89659
- const exists = deps.existsSync ?? existsSync81;
89660
- const readDir = deps.readDir ?? ((p) => readdirSync28(p));
89867
+ const exists = deps.existsSync ?? existsSync82;
89868
+ const readDir = deps.readDir ?? ((p) => readdirSync29(p));
89661
89869
  const root = trashRoot();
89662
89870
  if (!exists(root))
89663
89871
  return [];
89664
89872
  const out = [];
89665
89873
  for (const stamp of readDir(root)) {
89666
- const stampDir = join80(root, stamp);
89874
+ const stampDir = join81(root, stamp);
89667
89875
  let names;
89668
89876
  try {
89669
89877
  names = readDir(stampDir);
@@ -89671,7 +89879,7 @@ function listTrashEntries(nowMs, deps = {}) {
89671
89879
  continue;
89672
89880
  }
89673
89881
  for (const name of names) {
89674
- const p = join80(stampDir, name);
89882
+ const p = join81(stampDir, name);
89675
89883
  let mtimeMs = nowMs;
89676
89884
  try {
89677
89885
  mtimeMs = statSync45(p).mtimeMs;
@@ -89695,7 +89903,7 @@ function purgeTrash(paths) {
89695
89903
  return { deleted, errors: errors2 };
89696
89904
  }
89697
89905
  function defaultRoots() {
89698
- return [join80(homedir47(), "code")];
89906
+ return [join81(homedir47(), "code")];
89699
89907
  }
89700
89908
 
89701
89909
  // src/cli/worktree.ts
@@ -89918,12 +90126,12 @@ init_drive();
89918
90126
  init_scaffold_integration();
89919
90127
  import {
89920
90128
  chmodSync as chmodSync11,
89921
- mkdirSync as mkdirSync42,
89922
- readdirSync as readdirSync29,
90129
+ mkdirSync as mkdirSync43,
90130
+ readdirSync as readdirSync30,
89923
90131
  rmSync as rmSync16,
89924
- writeFileSync as writeFileSync24
90132
+ writeFileSync as writeFileSync25
89925
90133
  } from "node:fs";
89926
- import { join as join81 } from "node:path";
90134
+ import { join as join82 } from "node:path";
89927
90135
  function encodeCredentialsFilename(email) {
89928
90136
  const SAFE = new Set([
89929
90137
  ..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
@@ -90113,17 +90321,17 @@ function resolveCredentialsDir(env2) {
90113
90321
  if (explicit && explicit.length > 0)
90114
90322
  return explicit;
90115
90323
  const stateBase = env2.SWITCHROOM_CONTAINER === "1" ? "/state/agent" : env2.HOME ?? ".";
90116
- return join81(stateBase, "google-workspace-mcp", "credentials");
90324
+ return join82(stateBase, "google-workspace-mcp", "credentials");
90117
90325
  }
90118
90326
  function writeSeedFile(dir, email, seed) {
90119
- mkdirSync42(dir, { recursive: true, mode: 448 });
90327
+ mkdirSync43(dir, { recursive: true, mode: 448 });
90120
90328
  chmodSync11(dir, 448);
90121
- for (const name of readdirSync29(dir)) {
90122
- rmSync16(join81(dir, name), { force: true, recursive: true });
90329
+ for (const name of readdirSync30(dir)) {
90330
+ rmSync16(join82(dir, name), { force: true, recursive: true });
90123
90331
  }
90124
90332
  const filename = encodeCredentialsFilename(email);
90125
- const filePath = join81(dir, filename);
90126
- writeFileSync24(filePath, JSON.stringify(seed), { mode: 384 });
90333
+ const filePath = join82(dir, filename);
90334
+ writeFileSync25(filePath, JSON.stringify(seed), { mode: 384 });
90127
90335
  chmodSync11(filePath, 384);
90128
90336
  return filePath;
90129
90337
  }
@@ -90281,8 +90489,8 @@ function registerDriveMcpLauncherCommand(program3) {
90281
90489
  // src/cli/m365-mcp-launcher.ts
90282
90490
  init_scaffold_integration();
90283
90491
  import { spawn as spawn5 } from "node:child_process";
90284
- import { writeFileSync as writeFileSync25, mkdirSync as mkdirSync43 } from "node:fs";
90285
- import { dirname as dirname25, join as join82 } from "node:path";
90492
+ import { writeFileSync as writeFileSync26, mkdirSync as mkdirSync44 } from "node:fs";
90493
+ import { dirname as dirname27, join as join83 } from "node:path";
90286
90494
  var SOFTERIA_TOKEN_ENV = "MS365_MCP_OAUTH_TOKEN";
90287
90495
  var DEFAULT_REFRESH_LEAD_MS = 5 * 60 * 1000;
90288
90496
  var MAX_REFRESH_INTERVAL_MS = 60 * 60 * 1000;
@@ -90318,8 +90526,8 @@ function computeRefreshDelayMs(expiresAt, now, leadMs = DEFAULT_REFRESH_LEAD_MS)
90318
90526
  function writeRefreshHeartbeat(agentName, data, account) {
90319
90527
  const path8 = heartbeatPath(agentName, account);
90320
90528
  try {
90321
- mkdirSync43(dirname25(path8), { recursive: true });
90322
- writeFileSync25(path8, JSON.stringify(data, null, 2), { mode: 420 });
90529
+ mkdirSync44(dirname27(path8), { recursive: true });
90530
+ writeFileSync26(path8, JSON.stringify(data, null, 2), { mode: 420 });
90323
90531
  } catch {}
90324
90532
  }
90325
90533
  function heartbeatPath(agentName, account) {
@@ -90327,7 +90535,7 @@ function heartbeatPath(agentName, account) {
90327
90535
  const override = process.env.SWITCHROOM_M365_HEARTBEAT_DIR;
90328
90536
  if (override) {
90329
90537
  const base = slug ? `m365-launcher-${agentName}-${slug}` : `m365-launcher-${agentName}`;
90330
- return join82(override, `${base}.heartbeat.json`);
90538
+ return join83(override, `${base}.heartbeat.json`);
90331
90539
  }
90332
90540
  return slug ? `/state/agent/m365-launcher-${slug}.heartbeat.json` : "/state/agent/m365-launcher.heartbeat.json";
90333
90541
  }
@@ -90559,8 +90767,8 @@ function registerM365McpLauncherCommand(program3) {
90559
90767
  // src/cli/notion-mcp-launcher.ts
90560
90768
  init_scaffold_integration();
90561
90769
  import { spawn as spawn6 } from "node:child_process";
90562
- import { existsSync as existsSync82, mkdirSync as mkdirSync44, writeFileSync as writeFileSync26 } from "node:fs";
90563
- import { dirname as dirname26 } from "node:path";
90770
+ import { existsSync as existsSync83, mkdirSync as mkdirSync45, writeFileSync as writeFileSync27 } from "node:fs";
90771
+ import { dirname as dirname28 } from "node:path";
90564
90772
  var HEARTBEAT_WRITE_INTERVAL_MS = 30 * 1000;
90565
90773
  var DEFAULT_HEARTBEAT_PATH = "/state/agent/notion-launcher.heartbeat.json";
90566
90774
  var DEFAULT_VAULT_KEY = "notion/integration-token";
@@ -90570,10 +90778,10 @@ function buildNotionMcpArgs(opts) {
90570
90778
  }
90571
90779
  function defaultWriteHeartbeat(path8, contents) {
90572
90780
  try {
90573
- const dir = dirname26(path8);
90574
- if (!existsSync82(dir))
90575
- mkdirSync44(dir, { recursive: true });
90576
- writeFileSync26(path8, contents);
90781
+ const dir = dirname28(path8);
90782
+ if (!existsSync83(dir))
90783
+ mkdirSync45(dir, { recursive: true });
90784
+ writeFileSync27(path8, contents);
90577
90785
  } catch {}
90578
90786
  }
90579
90787
  async function runNotionMcpLauncher(opts, runtime) {
@@ -90683,9 +90891,9 @@ function registerNotionMcpLauncherCommand(program3) {
90683
90891
 
90684
90892
  // src/cli/hindsight-mcp-shim.ts
90685
90893
  init_hindsight();
90686
- import { mkdirSync as mkdirSync45, readFileSync as readFileSync70, renameSync as renameSync19, writeFileSync as writeFileSync27 } from "node:fs";
90894
+ import { mkdirSync as mkdirSync46, readFileSync as readFileSync71, renameSync as renameSync20, writeFileSync as writeFileSync28 } from "node:fs";
90687
90895
  import { tmpdir as tmpdir5 } from "node:os";
90688
- import { join as join83 } from "node:path";
90896
+ import { join as join84 } from "node:path";
90689
90897
  import { createInterface as createInterface6 } from "node:readline";
90690
90898
  var SHIM_SUPPORTED_PROTOCOL_VERSIONS = [
90691
90899
  "2025-06-18",
@@ -90908,22 +91116,22 @@ class HindsightShim {
90908
91116
  `));
90909
91117
  }
90910
91118
  get cachePath() {
90911
- return join83(this.opts.cacheDir, TOOLS_CACHE_FILENAME);
91119
+ return join84(this.opts.cacheDir, TOOLS_CACHE_FILENAME);
90912
91120
  }
90913
91121
  writeCache(result) {
90914
91122
  try {
90915
- mkdirSync45(this.opts.cacheDir, { recursive: true });
90916
- const tmp = join83(this.opts.cacheDir, `.${TOOLS_CACHE_FILENAME}.${process.pid}.tmp`);
90917
- writeFileSync27(tmp, JSON.stringify(result, null, 2) + `
91123
+ mkdirSync46(this.opts.cacheDir, { recursive: true });
91124
+ const tmp = join84(this.opts.cacheDir, `.${TOOLS_CACHE_FILENAME}.${process.pid}.tmp`);
91125
+ writeFileSync28(tmp, JSON.stringify(result, null, 2) + `
90918
91126
  `);
90919
- renameSync19(tmp, this.cachePath);
91127
+ renameSync20(tmp, this.cachePath);
90920
91128
  } catch (err) {
90921
91129
  this.log(`[hindsight-shim] cache write failed: ${String(err)}`);
90922
91130
  }
90923
91131
  }
90924
91132
  readCache() {
90925
91133
  try {
90926
- const parsed = JSON.parse(readFileSync70(this.cachePath, "utf-8"));
91134
+ const parsed = JSON.parse(readFileSync71(this.cachePath, "utf-8"));
90927
91135
  if (Array.isArray(parsed.tools))
90928
91136
  return parsed;
90929
91137
  return null;
@@ -91086,7 +91294,7 @@ function resolveShimOptionsFromEnv(env2) {
91086
91294
  return {
91087
91295
  url: env2.HINDSIGHT_MCP_URL || HINDSIGHT_DEFAULT_MCP_URL,
91088
91296
  bankId: env2.HINDSIGHT_BANK_ID || "",
91089
- cacheDir: env2.HINDSIGHT_SHIM_CACHE_DIR || join83(home2, ".hindsight-shim")
91297
+ cacheDir: env2.HINDSIGHT_SHIM_CACHE_DIR || join84(home2, ".hindsight-shim")
91090
91298
  };
91091
91299
  }
91092
91300
  function registerHindsightMcpShimCommand(program3) {
@@ -91099,7 +91307,7 @@ function registerHindsightMcpShimCommand(program3) {
91099
91307
 
91100
91308
  // src/cli/deliver-file.ts
91101
91309
  init_client2();
91102
- import { readFileSync as readFileSync71, statSync as statSync46 } from "node:fs";
91310
+ import { readFileSync as readFileSync72, statSync as statSync46 } from "node:fs";
91103
91311
  import { basename as basename11 } from "node:path";
91104
91312
 
91105
91313
  // src/delivery/onedrive.ts
@@ -91439,7 +91647,7 @@ async function defaultResolveProvider() {
91439
91647
  async function runDeliverFile(localPath, deps = {}) {
91440
91648
  const agentName = safeAgentName(deps.agentName ?? process.env.SWITCHROOM_AGENT_NAME);
91441
91649
  const sizeOf = deps.fileSize ?? ((p) => statSync46(p).size);
91442
- const read = deps.readFile ?? ((p) => new Uint8Array(readFileSync71(p)));
91650
+ const read = deps.readFile ?? ((p) => new Uint8Array(readFileSync72(p)));
91443
91651
  const resolveProvider = deps.resolveProvider ?? defaultResolveProvider;
91444
91652
  let size;
91445
91653
  try {
@@ -91760,8 +91968,8 @@ function runRedactStdin() {
91760
91968
  }
91761
91969
 
91762
91970
  // src/cli/status-ask.ts
91763
- import { readFileSync as readFileSync75, existsSync as existsSync87, readdirSync as readdirSync31 } from "node:fs";
91764
- import { join as join88 } from "node:path";
91971
+ import { readFileSync as readFileSync76, existsSync as existsSync88, readdirSync as readdirSync32 } from "node:fs";
91972
+ import { join as join89 } from "node:path";
91765
91973
  import { homedir as homedir50 } from "node:os";
91766
91974
 
91767
91975
  // src/status-ask/report.ts
@@ -92036,7 +92244,7 @@ function runReport(opts) {
92036
92244
  for (const src of sources) {
92037
92245
  let content;
92038
92246
  try {
92039
- content = readFileSync75(src.path, "utf-8");
92247
+ content = readFileSync76(src.path, "utf-8");
92040
92248
  } catch (err) {
92041
92249
  process.stderr.write(`status-ask report: cannot read ${src.path}: ${err instanceof Error ? err.message : String(err)}
92042
92250
  `);
@@ -92083,7 +92291,7 @@ function runReport(opts) {
92083
92291
  function resolveSources(explicitPath) {
92084
92292
  if (explicitPath != null && explicitPath.trim() !== "") {
92085
92293
  const trimmed = explicitPath.trim();
92086
- if (!existsSync87(trimmed)) {
92294
+ if (!existsSync88(trimmed)) {
92087
92295
  process.stderr.write(`status-ask report: ${trimmed}: file not found
92088
92296
  `);
92089
92297
  process.exit(1);
@@ -92097,20 +92305,20 @@ function resolveSources(explicitPath) {
92097
92305
  const config = loadConfig();
92098
92306
  agentsDir = resolveAgentsDir(config);
92099
92307
  } catch {
92100
- agentsDir = join88(homedir50(), ".switchroom", "agents");
92308
+ agentsDir = join89(homedir50(), ".switchroom", "agents");
92101
92309
  }
92102
- if (!existsSync87(agentsDir))
92310
+ if (!existsSync88(agentsDir))
92103
92311
  return [];
92104
92312
  const sources = [];
92105
92313
  let entries;
92106
92314
  try {
92107
- entries = readdirSync31(agentsDir);
92315
+ entries = readdirSync32(agentsDir);
92108
92316
  } catch {
92109
92317
  return [];
92110
92318
  }
92111
92319
  for (const name of entries) {
92112
- const path9 = join88(agentsDir, name, "runtime-metrics.jsonl");
92113
- if (existsSync87(path9)) {
92320
+ const path9 = join89(agentsDir, name, "runtime-metrics.jsonl");
92321
+ if (existsSync88(path9)) {
92114
92322
  sources.push({ path: path9, agent: name });
92115
92323
  }
92116
92324
  }
@@ -92140,45 +92348,45 @@ var import_yaml21 = __toESM(require_dist(), 1);
92140
92348
  init_paths();
92141
92349
  import {
92142
92350
  closeSync as closeSync14,
92143
- existsSync as existsSync88,
92351
+ existsSync as existsSync89,
92144
92352
  fsyncSync as fsyncSync8,
92145
- mkdirSync as mkdirSync50,
92353
+ mkdirSync as mkdirSync51,
92146
92354
  openSync as openSync14,
92147
- readdirSync as readdirSync32,
92148
- readFileSync as readFileSync76,
92149
- renameSync as renameSync21,
92355
+ readdirSync as readdirSync33,
92356
+ readFileSync as readFileSync77,
92357
+ renameSync as renameSync22,
92150
92358
  statSync as statSync48,
92151
92359
  unlinkSync as unlinkSync18,
92152
92360
  writeSync as writeSync10
92153
92361
  } from "node:fs";
92154
- import { join as join89, resolve as resolve53 } from "node:path";
92362
+ import { join as join90, resolve as resolve53 } from "node:path";
92155
92363
  var STAGING_SUBDIR = ".staging";
92156
92364
  function overlayPathsFor(agent, opts = {}) {
92157
92365
  const base = opts.root ? resolve53(opts.root, agent) : resolve53(resolveDualPath(`~/.switchroom/agents/${agent}`));
92158
- const scheduleDir = join89(base, "schedule.d");
92159
- const scheduleStagingDir = join89(scheduleDir, STAGING_SUBDIR);
92160
- const skillsDir = join89(base, "skills.d");
92161
- const skillsStagingDir = join89(skillsDir, STAGING_SUBDIR);
92366
+ const scheduleDir = join90(base, "schedule.d");
92367
+ const scheduleStagingDir = join90(scheduleDir, STAGING_SUBDIR);
92368
+ const skillsDir = join90(base, "skills.d");
92369
+ const skillsStagingDir = join90(skillsDir, STAGING_SUBDIR);
92162
92370
  return {
92163
92371
  agentRoot: base,
92164
92372
  scheduleDir,
92165
92373
  scheduleStagingDir,
92166
92374
  skillsDir,
92167
92375
  skillsStagingDir,
92168
- lockPath: join89(base, ".lock"),
92376
+ lockPath: join90(base, ".lock"),
92169
92377
  stagingDir: scheduleStagingDir
92170
92378
  };
92171
92379
  }
92172
92380
  function ensureDirs(paths) {
92173
- mkdirSync50(paths.scheduleDir, { recursive: true });
92174
- mkdirSync50(paths.scheduleStagingDir, { recursive: true });
92381
+ mkdirSync51(paths.scheduleDir, { recursive: true });
92382
+ mkdirSync51(paths.scheduleStagingDir, { recursive: true });
92175
92383
  }
92176
92384
  function ensureSkillsDirs(paths) {
92177
- mkdirSync50(paths.skillsDir, { recursive: true });
92178
- mkdirSync50(paths.skillsStagingDir, { recursive: true });
92385
+ mkdirSync51(paths.skillsDir, { recursive: true });
92386
+ mkdirSync51(paths.skillsStagingDir, { recursive: true });
92179
92387
  }
92180
92388
  function withAgentLock(paths, fn) {
92181
- mkdirSync50(paths.agentRoot, { recursive: true });
92389
+ mkdirSync51(paths.agentRoot, { recursive: true });
92182
92390
  const start = Date.now();
92183
92391
  const TIMEOUT_MS = 5000;
92184
92392
  let fd = null;
@@ -92219,8 +92427,8 @@ function writeOverlayEntry(agent, slug, yamlText, opts = {}) {
92219
92427
  const paths = overlayPathsFor(agent, opts);
92220
92428
  return withAgentLock(paths, () => {
92221
92429
  ensureDirs(paths);
92222
- const stagingPath = join89(paths.scheduleStagingDir, `${slug}.yaml`);
92223
- const finalPath = join89(paths.scheduleDir, `${slug}.yaml`);
92430
+ const stagingPath = join90(paths.scheduleStagingDir, `${slug}.yaml`);
92431
+ const finalPath = join90(paths.scheduleDir, `${slug}.yaml`);
92224
92432
  const fd = openSync14(stagingPath, "w", 384);
92225
92433
  try {
92226
92434
  writeSync10(fd, yamlText);
@@ -92228,7 +92436,7 @@ function writeOverlayEntry(agent, slug, yamlText, opts = {}) {
92228
92436
  } finally {
92229
92437
  closeSync14(fd);
92230
92438
  }
92231
- renameSync21(stagingPath, finalPath);
92439
+ renameSync22(stagingPath, finalPath);
92232
92440
  return finalPath;
92233
92441
  });
92234
92442
  }
@@ -92236,8 +92444,8 @@ function writeSkillsOverlayEntry(agent, slug, yamlText, opts = {}) {
92236
92444
  const paths = overlayPathsFor(agent, opts);
92237
92445
  return withAgentLock(paths, () => {
92238
92446
  ensureSkillsDirs(paths);
92239
- const stagingPath = join89(paths.skillsStagingDir, `${slug}.yaml`);
92240
- const finalPath = join89(paths.skillsDir, `${slug}.yaml`);
92447
+ const stagingPath = join90(paths.skillsStagingDir, `${slug}.yaml`);
92448
+ const finalPath = join90(paths.skillsDir, `${slug}.yaml`);
92241
92449
  const fd = openSync14(stagingPath, "w", 384);
92242
92450
  try {
92243
92451
  writeSync10(fd, yamlText);
@@ -92245,15 +92453,15 @@ function writeSkillsOverlayEntry(agent, slug, yamlText, opts = {}) {
92245
92453
  } finally {
92246
92454
  closeSync14(fd);
92247
92455
  }
92248
- renameSync21(stagingPath, finalPath);
92456
+ renameSync22(stagingPath, finalPath);
92249
92457
  return finalPath;
92250
92458
  });
92251
92459
  }
92252
92460
  function deleteSkillsOverlayEntry(agent, slug, opts = {}) {
92253
92461
  const paths = overlayPathsFor(agent, opts);
92254
92462
  return withAgentLock(paths, () => {
92255
- const finalPath = join89(paths.skillsDir, `${slug}.yaml`);
92256
- if (!existsSync88(finalPath))
92463
+ const finalPath = join90(paths.skillsDir, `${slug}.yaml`);
92464
+ if (!existsSync89(finalPath))
92257
92465
  return false;
92258
92466
  unlinkSync18(finalPath);
92259
92467
  return true;
@@ -92261,15 +92469,15 @@ function deleteSkillsOverlayEntry(agent, slug, opts = {}) {
92261
92469
  }
92262
92470
  function listSkillsOverlayEntries(agent, opts = {}) {
92263
92471
  const paths = overlayPathsFor(agent, opts);
92264
- if (!existsSync88(paths.skillsDir))
92472
+ if (!existsSync89(paths.skillsDir))
92265
92473
  return [];
92266
92474
  const out = [];
92267
- for (const name of readdirSync32(paths.skillsDir)) {
92475
+ for (const name of readdirSync33(paths.skillsDir)) {
92268
92476
  if (!/\.ya?ml$/i.test(name))
92269
92477
  continue;
92270
- const full = join89(paths.skillsDir, name);
92478
+ const full = join90(paths.skillsDir, name);
92271
92479
  try {
92272
- const raw = readFileSync76(full, "utf-8");
92480
+ const raw = readFileSync77(full, "utf-8");
92273
92481
  const slug = name.replace(/\.ya?ml$/i, "");
92274
92482
  out.push({ slug, path: full, raw });
92275
92483
  } catch {}
@@ -92279,8 +92487,8 @@ function listSkillsOverlayEntries(agent, opts = {}) {
92279
92487
  function deleteOverlayEntry(agent, slug, opts = {}) {
92280
92488
  const paths = overlayPathsFor(agent, opts);
92281
92489
  return withAgentLock(paths, () => {
92282
- const finalPath = join89(paths.scheduleDir, `${slug}.yaml`);
92283
- if (!existsSync88(finalPath))
92490
+ const finalPath = join90(paths.scheduleDir, `${slug}.yaml`);
92491
+ if (!existsSync89(finalPath))
92284
92492
  return false;
92285
92493
  unlinkSync18(finalPath);
92286
92494
  return true;
@@ -92288,15 +92496,15 @@ function deleteOverlayEntry(agent, slug, opts = {}) {
92288
92496
  }
92289
92497
  function listOverlayEntries(agent, opts = {}) {
92290
92498
  const paths = overlayPathsFor(agent, opts);
92291
- if (!existsSync88(paths.scheduleDir))
92499
+ if (!existsSync89(paths.scheduleDir))
92292
92500
  return [];
92293
92501
  const out = [];
92294
- for (const name of readdirSync32(paths.scheduleDir)) {
92502
+ for (const name of readdirSync33(paths.scheduleDir)) {
92295
92503
  if (!/\.ya?ml$/i.test(name))
92296
92504
  continue;
92297
- const full = join89(paths.scheduleDir, name);
92505
+ const full = join90(paths.scheduleDir, name);
92298
92506
  try {
92299
- const raw = readFileSync76(full, "utf-8");
92507
+ const raw = readFileSync77(full, "utf-8");
92300
92508
  const slug = name.replace(/\.ya?ml$/i, "");
92301
92509
  out.push({ slug, path: full, raw });
92302
92510
  } catch {}
@@ -92516,27 +92724,27 @@ function reconcileAgentCronOnly(agent) {
92516
92724
  // src/cli/agent-config-pending.ts
92517
92725
  import {
92518
92726
  closeSync as closeSync15,
92519
- existsSync as existsSync89,
92727
+ existsSync as existsSync90,
92520
92728
  fsyncSync as fsyncSync9,
92521
- mkdirSync as mkdirSync51,
92729
+ mkdirSync as mkdirSync52,
92522
92730
  openSync as openSync15,
92523
- readdirSync as readdirSync33,
92524
- readFileSync as readFileSync77,
92525
- renameSync as renameSync22,
92731
+ readdirSync as readdirSync34,
92732
+ readFileSync as readFileSync78,
92733
+ renameSync as renameSync23,
92526
92734
  unlinkSync as unlinkSync19,
92527
- writeFileSync as writeFileSync32,
92735
+ writeFileSync as writeFileSync33,
92528
92736
  writeSync as writeSync11
92529
92737
  } from "node:fs";
92530
- import { join as join90 } from "node:path";
92738
+ import { join as join91 } from "node:path";
92531
92739
  import { randomBytes as randomBytes15 } from "node:crypto";
92532
92740
  var STAGE_ID_PREFIX = "cap_";
92533
92741
  function pendingDir(agent, opts = {}) {
92534
92742
  const paths = overlayPathsFor(agent, opts);
92535
- return join90(paths.scheduleDir, ".pending");
92743
+ return join91(paths.scheduleDir, ".pending");
92536
92744
  }
92537
92745
  function ensurePendingDir(agent, opts = {}) {
92538
92746
  const dir = pendingDir(agent, opts);
92539
- mkdirSync51(dir, { recursive: true });
92747
+ mkdirSync52(dir, { recursive: true });
92540
92748
  return dir;
92541
92749
  }
92542
92750
  function newStageId() {
@@ -92545,8 +92753,8 @@ function newStageId() {
92545
92753
  function stagePendingScheduleEntry(opts) {
92546
92754
  const dir = ensurePendingDir(opts.agent, { root: opts.root });
92547
92755
  const stageId = opts.stageId ?? newStageId();
92548
- const yamlPath = join90(dir, `${stageId}.yaml`);
92549
- const metaPath = join90(dir, `${stageId}.meta.json`);
92756
+ const yamlPath = join91(dir, `${stageId}.yaml`);
92757
+ const metaPath = join91(dir, `${stageId}.meta.json`);
92550
92758
  const meta = {
92551
92759
  v: 1,
92552
92760
  stage_id: stageId,
@@ -92565,27 +92773,27 @@ function stagePendingScheduleEntry(opts) {
92565
92773
  } finally {
92566
92774
  closeSync15(fd);
92567
92775
  }
92568
- renameSync22(yamlTmp, yamlPath);
92776
+ renameSync23(yamlTmp, yamlPath);
92569
92777
  }
92570
- writeFileSync32(metaPath, JSON.stringify(meta, null, 2) + `
92778
+ writeFileSync33(metaPath, JSON.stringify(meta, null, 2) + `
92571
92779
  `, { mode: 384 });
92572
92780
  return { stageId, yamlPath, metaPath };
92573
92781
  }
92574
92782
  function listPendingScheduleEntries(agent, opts = {}) {
92575
92783
  const dir = pendingDir(agent, opts);
92576
- if (!existsSync89(dir))
92784
+ if (!existsSync90(dir))
92577
92785
  return [];
92578
92786
  const out = [];
92579
- for (const name of readdirSync33(dir).sort()) {
92787
+ for (const name of readdirSync34(dir).sort()) {
92580
92788
  if (!name.endsWith(".meta.json"))
92581
92789
  continue;
92582
92790
  const stageId = name.slice(0, -".meta.json".length);
92583
- const metaPath = join90(dir, name);
92584
- const yamlPath = join90(dir, `${stageId}.yaml`);
92585
- if (!existsSync89(yamlPath))
92791
+ const metaPath = join91(dir, name);
92792
+ const yamlPath = join91(dir, `${stageId}.yaml`);
92793
+ if (!existsSync90(yamlPath))
92586
92794
  continue;
92587
92795
  try {
92588
- const meta = JSON.parse(readFileSync77(metaPath, "utf-8"));
92796
+ const meta = JSON.parse(readFileSync78(metaPath, "utf-8"));
92589
92797
  if (meta?.v !== 1 || typeof meta.stage_id !== "string")
92590
92798
  continue;
92591
92799
  out.push({ stageId: meta.stage_id, agent: meta.agent, yamlPath, metaPath, meta });
@@ -92600,11 +92808,11 @@ function commitPendingScheduleEntry(opts) {
92600
92808
  return { committed: false, reason: "not_found" };
92601
92809
  const slug = match.meta.entry.name ?? match.stageId;
92602
92810
  const paths = overlayPathsFor(opts.agent, { root: opts.root });
92603
- const finalPath = join90(paths.scheduleDir, `${slug}.yaml`);
92604
- if (existsSync89(finalPath)) {
92811
+ const finalPath = join91(paths.scheduleDir, `${slug}.yaml`);
92812
+ if (existsSync90(finalPath)) {
92605
92813
  return { committed: false, reason: "slug_collision" };
92606
92814
  }
92607
- renameSync22(match.yamlPath, finalPath);
92815
+ renameSync23(match.yamlPath, finalPath);
92608
92816
  unlinkSync19(match.metaPath);
92609
92817
  return { committed: true, path: finalPath, slug };
92610
92818
  }
@@ -92623,7 +92831,7 @@ function denyPendingScheduleEntry(opts) {
92623
92831
  }
92624
92832
 
92625
92833
  // src/cli/agent-config-write.ts
92626
- import { existsSync as existsSync90, readFileSync as readFileSync78 } from "node:fs";
92834
+ import { existsSync as existsSync91, readFileSync as readFileSync79 } from "node:fs";
92627
92835
  import { execFileSync as execFileSync28 } from "node:child_process";
92628
92836
 
92629
92837
  // src/scheduler/schedule-report.ts
@@ -93013,8 +93221,8 @@ function scheduleRemove(opts) {
93013
93221
  }
93014
93222
  let priorContent = null;
93015
93223
  try {
93016
- if (existsSync90(match.path))
93017
- priorContent = readFileSync78(match.path, "utf-8");
93224
+ if (existsSync91(match.path))
93225
+ priorContent = readFileSync79(match.path, "utf-8");
93018
93226
  } catch {}
93019
93227
  deleteOverlayEntry(agent, match.slug, { root: opts.root });
93020
93228
  const reconcileFn = opts.reconcile === undefined ? opts.root ? null : reconcileAgentCronOnly : opts.reconcile;
@@ -93217,7 +93425,7 @@ function registerAgentConfigWriteCommands(program3) {
93217
93425
  }
93218
93426
  let blob;
93219
93427
  if (opts.jsonl) {
93220
- blob = existsSync90(opts.jsonl) ? readFileSync78(opts.jsonl, "utf-8") : "";
93428
+ blob = existsSync91(opts.jsonl) ? readFileSync79(opts.jsonl, "utf-8") : "";
93221
93429
  } else {
93222
93430
  try {
93223
93431
  blob = execFileSync28("docker", ["exec", `switchroom-${agent}`, "cat", "/state/agent/scheduler.jsonl"], {
@@ -93249,11 +93457,11 @@ function registerAgentConfigWriteCommands(program3) {
93249
93457
 
93250
93458
  // src/cli/agent-config-skill-write.ts
93251
93459
  var import_yaml22 = __toESM(require_dist(), 1);
93252
- import { existsSync as existsSync91 } from "node:fs";
93460
+ import { existsSync as existsSync92 } from "node:fs";
93253
93461
  init_reconcile_default_skills();
93254
93462
  init_agent_config();
93255
93463
  var import_yaml23 = __toESM(require_dist(), 1);
93256
- import { join as join91 } from "node:path";
93464
+ import { join as join92 } from "node:path";
93257
93465
  var MAX_SKILLS_PER_AGENT = 20;
93258
93466
  var V1_ALLOWED_SOURCE_PREFIX = "bundled:";
93259
93467
  function exitCodeFor2(code) {
@@ -93328,8 +93536,8 @@ function skillInstall(opts) {
93328
93536
  return err("E_SKILL_QUOTA_EXCEEDED", `agent ${agent} already has ${used} overlay-installed skills (cap ${MAX_SKILLS_PER_AGENT})`);
93329
93537
  }
93330
93538
  const poolDir = opts.bundledSkillsPoolDir ?? getBundledSkillsPoolDir();
93331
- const skillPath = join91(poolDir, skillName);
93332
- if (!existsSync91(skillPath)) {
93539
+ const skillPath = join92(poolDir, skillName);
93540
+ if (!existsSync92(skillPath)) {
93333
93541
  return err("E_SKILL_NOT_FOUND", `bundled skill not found at ${skillPath}. The operator needs to ` + `place the skill at this path before the agent can opt in.`);
93334
93542
  }
93335
93543
  const yamlText = import_yaml22.stringify({ skills: [skillName] });
@@ -93493,21 +93701,21 @@ function registerAgentConfigSkillWriteCommands(program3) {
93493
93701
  // src/cli/skill.ts
93494
93702
  import {
93495
93703
  closeSync as closeSync16,
93496
- existsSync as existsSync92,
93704
+ existsSync as existsSync93,
93497
93705
  lstatSync as lstatSync11,
93498
- mkdirSync as mkdirSync52,
93706
+ mkdirSync as mkdirSync53,
93499
93707
  mkdtempSync as mkdtempSync5,
93500
93708
  openSync as openSync16,
93501
- readFileSync as readFileSync79,
93502
- readdirSync as readdirSync34,
93709
+ readFileSync as readFileSync80,
93710
+ readdirSync as readdirSync35,
93503
93711
  realpathSync as realpathSync7,
93504
- renameSync as renameSync23,
93712
+ renameSync as renameSync24,
93505
93713
  rmSync as rmSync18,
93506
93714
  statSync as statSync49,
93507
- writeFileSync as writeFileSync33
93715
+ writeFileSync as writeFileSync34
93508
93716
  } from "node:fs";
93509
93717
  import { tmpdir as tmpdir6, homedir as homedir51 } from "node:os";
93510
- import { dirname as dirname31, join as join92, relative as relative2, resolve as resolve54 } from "node:path";
93718
+ import { dirname as dirname33, join as join93, relative as relative4, resolve as resolve54 } from "node:path";
93511
93719
  import { spawnSync as spawnSync16 } from "node:child_process";
93512
93720
 
93513
93721
  // src/cli/skill-common.ts
@@ -93741,7 +93949,7 @@ function scanForClaudeP2(content) {
93741
93949
  function resolveSkillsPoolDir2(override) {
93742
93950
  const raw = override ?? "~/.switchroom/skills";
93743
93951
  if (raw.startsWith("~/")) {
93744
- return join92(homedir51(), raw.slice(2));
93952
+ return join93(homedir51(), raw.slice(2));
93745
93953
  }
93746
93954
  if (raw === "~")
93747
93955
  return homedir51();
@@ -93778,10 +93986,10 @@ function loadFromDir(dir) {
93778
93986
  }
93779
93987
  const files = {};
93780
93988
  const walk2 = (sub) => {
93781
- const entries = readdirSync34(sub, { withFileTypes: true });
93989
+ const entries = readdirSync35(sub, { withFileTypes: true });
93782
93990
  for (const ent of entries) {
93783
- const full = join92(sub, ent.name);
93784
- const rel = relative2(abs, full);
93991
+ const full = join93(sub, ent.name);
93992
+ const rel = relative4(abs, full);
93785
93993
  if (ent.isSymbolicLink()) {
93786
93994
  fail3(`refusing to read symlink inside --from dir: ${rel}`);
93787
93995
  }
@@ -93790,7 +93998,7 @@ function loadFromDir(dir) {
93790
93998
  continue;
93791
93999
  }
93792
94000
  if (ent.isFile()) {
93793
- const buf = readFileSync79(full);
94001
+ const buf = readFileSync80(full);
93794
94002
  files[rel.replace(/\\/g, "/")] = buf.toString("utf-8");
93795
94003
  }
93796
94004
  }
@@ -93815,7 +94023,7 @@ function loadFromTarball(tarPath) {
93815
94023
  fail3(`tarball contains disallowed path: ${JSON.stringify(entry)} \u2014 ` + `refusing to extract before any file is written`);
93816
94024
  }
93817
94025
  }
93818
- const staging = mkdtempSync5(join92(tmpdir6(), "skill-apply-extract-"));
94026
+ const staging = mkdtempSync5(join93(tmpdir6(), "skill-apply-extract-"));
93819
94027
  try {
93820
94028
  const flags = isGz ? ["-xzf"] : ["-xf"];
93821
94029
  const r = spawnSync16("tar", [
@@ -93839,7 +94047,7 @@ function loadFromTarball(tarPath) {
93839
94047
  }
93840
94048
  }
93841
94049
  function loadSingleFile(filePath) {
93842
- const content = readFileSync79(filePath, "utf-8");
94050
+ const content = readFileSync80(filePath, "utf-8");
93843
94051
  return { "SKILL.md": content };
93844
94052
  }
93845
94053
  function loadFromStdin() {
@@ -93901,10 +94109,10 @@ function validatePayload(name, files) {
93901
94109
  errors2.push(`${path9} fails \`bash -n\` syntax check: ${(r.stderr ?? "").trim()}`);
93902
94110
  }
93903
94111
  } else if (PY_SCRIPT_RE2.test(path9)) {
93904
- const tmp = mkdtempSync5(join92(tmpdir6(), "skill-apply-py-"));
93905
- const tmpPy = join92(tmp, "check.py");
94112
+ const tmp = mkdtempSync5(join93(tmpdir6(), "skill-apply-py-"));
94113
+ const tmpPy = join93(tmp, "check.py");
93906
94114
  try {
93907
- writeFileSync33(tmpPy, content);
94115
+ writeFileSync34(tmpPy, content);
93908
94116
  const r = spawnSync16("python3", ["-m", "py_compile", tmpPy], {
93909
94117
  encoding: "utf-8"
93910
94118
  });
@@ -93922,15 +94130,15 @@ function validatePayload(name, files) {
93922
94130
  function diffSummary(currentDir, files) {
93923
94131
  const lines = [];
93924
94132
  const currentFiles = {};
93925
- if (existsSync92(currentDir)) {
94133
+ if (existsSync93(currentDir)) {
93926
94134
  const walk2 = (sub) => {
93927
- for (const ent of readdirSync34(sub, { withFileTypes: true })) {
93928
- const full = join92(sub, ent.name);
93929
- const rel = relative2(currentDir, full);
94135
+ for (const ent of readdirSync35(sub, { withFileTypes: true })) {
94136
+ const full = join93(sub, ent.name);
94137
+ const rel = relative4(currentDir, full);
93930
94138
  if (ent.isDirectory()) {
93931
94139
  walk2(full);
93932
94140
  } else if (ent.isFile()) {
93933
- currentFiles[rel.replace(/\\/g, "/")] = readFileSync79(full, "utf-8");
94141
+ currentFiles[rel.replace(/\\/g, "/")] = readFileSync80(full, "utf-8");
93934
94142
  }
93935
94143
  }
93936
94144
  };
@@ -93958,10 +94166,10 @@ function diffSummary(currentDir, files) {
93958
94166
  `);
93959
94167
  }
93960
94168
  function writePayload(poolDir, name, files) {
93961
- if (!existsSync92(poolDir)) {
93962
- mkdirSync52(poolDir, { recursive: true, mode: 493 });
94169
+ if (!existsSync93(poolDir)) {
94170
+ mkdirSync53(poolDir, { recursive: true, mode: 493 });
93963
94171
  }
93964
- const target = join92(poolDir, name);
94172
+ const target = join93(poolDir, name);
93965
94173
  let targetIsSymlink = false;
93966
94174
  try {
93967
94175
  const st = lstatSync11(target);
@@ -93972,15 +94180,15 @@ function writePayload(poolDir, name, files) {
93972
94180
  if (targetIsSymlink) {
93973
94181
  fail3(`refusing to overwrite symlink at ${target}; investigate manually`);
93974
94182
  }
93975
- const staging = mkdtempSync5(join92(poolDir, `.skill-apply-stage-${name}-`));
94183
+ const staging = mkdtempSync5(join93(poolDir, `.skill-apply-stage-${name}-`));
93976
94184
  let oldRename = null;
93977
94185
  try {
93978
94186
  for (const [path9, content] of Object.entries(files)) {
93979
- const full = join92(staging, path9);
93980
- mkdirSync52(dirname31(full), { recursive: true, mode: 493 });
94187
+ const full = join93(staging, path9);
94188
+ mkdirSync53(dirname33(full), { recursive: true, mode: 493 });
93981
94189
  const fd = openSync16(full, "wx");
93982
94190
  try {
93983
- writeFileSync33(fd, content);
94191
+ writeFileSync34(fd, content);
93984
94192
  } finally {
93985
94193
  closeSync16(fd);
93986
94194
  }
@@ -93996,9 +94204,9 @@ function writePayload(poolDir, name, files) {
93996
94204
  } catch {}
93997
94205
  if (targetExists) {
93998
94206
  oldRename = `${target}.skill-apply-old-${Date.now()}`;
93999
- renameSync23(target, oldRename);
94207
+ renameSync24(target, oldRename);
94000
94208
  }
94001
- renameSync23(staging, target);
94209
+ renameSync24(staging, target);
94002
94210
  if (oldRename) {
94003
94211
  rmSync18(oldRename, { recursive: true, force: true });
94004
94212
  oldRename = null;
@@ -94007,12 +94215,12 @@ function writePayload(poolDir, name, files) {
94007
94215
  try {
94008
94216
  rmSync18(staging, { recursive: true, force: true });
94009
94217
  } catch {}
94010
- if (oldRename && existsSync92(oldRename)) {
94218
+ if (oldRename && existsSync93(oldRename)) {
94011
94219
  try {
94012
- if (existsSync92(target)) {
94220
+ if (existsSync93(target)) {
94013
94221
  rmSync18(target, { recursive: true, force: true });
94014
94222
  }
94015
- renameSync23(oldRename, target);
94223
+ renameSync24(oldRename, target);
94016
94224
  } catch {}
94017
94225
  }
94018
94226
  throw err2;
@@ -94030,7 +94238,7 @@ function registerSkillCommand(program3) {
94030
94238
  files = loadFromStdin();
94031
94239
  } else {
94032
94240
  const fromPath = resolve54(opts.from);
94033
- if (!existsSync92(fromPath)) {
94241
+ if (!existsSync93(fromPath)) {
94034
94242
  fail3(`--from path does not exist: ${opts.from}`);
94035
94243
  }
94036
94244
  const st = statSync49(fromPath);
@@ -94054,7 +94262,7 @@ function registerSkillCommand(program3) {
94054
94262
  }
94055
94263
  const config = loadConfig();
94056
94264
  const poolDir = resolveSkillsPoolDir2(config.switchroom?.skills_dir);
94057
- const currentDir = join92(poolDir, name);
94265
+ const currentDir = join93(poolDir, name);
94058
94266
  console.log(source_default.bold(`Skill: ${name}`) + source_default.gray(` (${Object.keys(files).length} files, ${sumBytes(files)} bytes)`));
94059
94267
  console.log(source_default.bold("Diff vs current pool content:"));
94060
94268
  console.log(diffSummary(currentDir, files));
@@ -94086,20 +94294,20 @@ function sumBytes(files) {
94086
94294
  init_esm();
94087
94295
  import {
94088
94296
  closeSync as closeSync17,
94089
- existsSync as existsSync93,
94297
+ existsSync as existsSync94,
94090
94298
  lstatSync as lstatSync12,
94091
- mkdirSync as mkdirSync53,
94299
+ mkdirSync as mkdirSync54,
94092
94300
  mkdtempSync as mkdtempSync6,
94093
94301
  openSync as openSync17,
94094
- readFileSync as readFileSync80,
94095
- readdirSync as readdirSync35,
94096
- renameSync as renameSync24,
94302
+ readFileSync as readFileSync81,
94303
+ readdirSync as readdirSync36,
94304
+ renameSync as renameSync25,
94097
94305
  rmSync as rmSync19,
94098
94306
  statSync as statSync50,
94099
94307
  utimesSync,
94100
- writeFileSync as writeFileSync34
94308
+ writeFileSync as writeFileSync35
94101
94309
  } from "node:fs";
94102
- import { dirname as dirname32, join as join93, relative as relative3, resolve as resolve55 } from "node:path";
94310
+ import { dirname as dirname34, join as join94, relative as relative5, resolve as resolve55 } from "node:path";
94103
94311
  import { homedir as homedir52, tmpdir as tmpdir7 } from "node:os";
94104
94312
  import { spawnSync as spawnSync17 } from "node:child_process";
94105
94313
  init_helpers();
@@ -94111,18 +94319,18 @@ var TRASH_TTL_MS = 24 * 60 * 60 * 1000;
94111
94319
  var PERSONAL_SKILLS_SUBPATH = "personal-skills";
94112
94320
  function resolveConfigSkillsDir(agent) {
94113
94321
  const override = process.env.SWITCHROOM_CONFIG_DIR;
94114
- const candidate = override ? resolve55(override) : join93(homedir52(), ".switchroom-config");
94115
- if (!existsSync93(candidate))
94322
+ const candidate = override ? resolve55(override) : join94(homedir52(), ".switchroom-config");
94323
+ if (!existsSync94(candidate))
94116
94324
  return null;
94117
- return join93(candidate, "agents", agent, PERSONAL_SKILLS_SUBPATH);
94325
+ return join94(candidate, "agents", agent, PERSONAL_SKILLS_SUBPATH);
94118
94326
  }
94119
94327
  var MIRROR_PRIOR_TTL_MS = 24 * 60 * 60 * 1000;
94120
94328
  function sweepMirrorPriors(configSkillsRoot) {
94121
94329
  try {
94122
- if (!existsSync93(configSkillsRoot))
94330
+ if (!existsSync94(configSkillsRoot))
94123
94331
  return;
94124
94332
  const now = Date.now();
94125
- for (const ent of readdirSync35(configSkillsRoot)) {
94333
+ for (const ent of readdirSync36(configSkillsRoot)) {
94126
94334
  const m = /^\.(?:.+)-(?:prior|trash)-(\d+)$/.exec(ent);
94127
94335
  if (!m)
94128
94336
  continue;
@@ -94132,7 +94340,7 @@ function sweepMirrorPriors(configSkillsRoot) {
94132
94340
  if (now - ts < MIRROR_PRIOR_TTL_MS)
94133
94341
  continue;
94134
94342
  try {
94135
- rmSync19(join93(configSkillsRoot, ent), { recursive: true, force: true });
94343
+ rmSync19(join94(configSkillsRoot, ent), { recursive: true, force: true });
94136
94344
  } catch {}
94137
94345
  }
94138
94346
  } catch {}
@@ -94141,7 +94349,7 @@ function mirrorToConfigRepo(agent, name, liveSkillDir) {
94141
94349
  const configSkillsRoot = resolveConfigSkillsDir(agent);
94142
94350
  if (!configSkillsRoot)
94143
94351
  return;
94144
- const dest = join93(configSkillsRoot, name);
94352
+ const dest = join94(configSkillsRoot, name);
94145
94353
  try {
94146
94354
  if (liveSkillDir !== null) {
94147
94355
  try {
@@ -94155,35 +94363,35 @@ function mirrorToConfigRepo(agent, name, liveSkillDir) {
94155
94363
  }
94156
94364
  if (liveSkillDir === null) {
94157
94365
  sweepMirrorPriors(configSkillsRoot);
94158
- if (existsSync93(dest)) {
94159
- const trash = join93(configSkillsRoot, `.${name}-trash-${Date.now()}`);
94160
- renameSync24(dest, trash);
94366
+ if (existsSync94(dest)) {
94367
+ const trash = join94(configSkillsRoot, `.${name}-trash-${Date.now()}`);
94368
+ renameSync25(dest, trash);
94161
94369
  }
94162
94370
  return;
94163
94371
  }
94164
- mkdirSync53(configSkillsRoot, { recursive: true, mode: 493 });
94372
+ mkdirSync54(configSkillsRoot, { recursive: true, mode: 493 });
94165
94373
  sweepMirrorPriors(configSkillsRoot);
94166
- const staging = mkdtempSync6(join93(configSkillsRoot, `.${name}-staging-`));
94374
+ const staging = mkdtempSync6(join94(configSkillsRoot, `.${name}-staging-`));
94167
94375
  const walk2 = (src, dst) => {
94168
- mkdirSync53(dst, { recursive: true, mode: 493 });
94169
- for (const ent of readdirSync35(src, { withFileTypes: true })) {
94170
- const s = join93(src, ent.name);
94171
- const d = join93(dst, ent.name);
94376
+ mkdirSync54(dst, { recursive: true, mode: 493 });
94377
+ for (const ent of readdirSync36(src, { withFileTypes: true })) {
94378
+ const s = join94(src, ent.name);
94379
+ const d = join94(dst, ent.name);
94172
94380
  if (ent.isSymbolicLink())
94173
94381
  continue;
94174
94382
  if (ent.isDirectory())
94175
94383
  walk2(s, d);
94176
94384
  else if (ent.isFile()) {
94177
- writeFileSync34(d, readFileSync80(s));
94385
+ writeFileSync35(d, readFileSync81(s));
94178
94386
  }
94179
94387
  }
94180
94388
  };
94181
94389
  walk2(liveSkillDir, staging);
94182
- if (existsSync93(dest)) {
94183
- const prior = join93(configSkillsRoot, `.${name}-prior-${Date.now()}`);
94184
- renameSync24(dest, prior);
94390
+ if (existsSync94(dest)) {
94391
+ const prior = join94(configSkillsRoot, `.${name}-prior-${Date.now()}`);
94392
+ renameSync25(dest, prior);
94185
94393
  }
94186
- renameSync24(staging, dest);
94394
+ renameSync25(staging, dest);
94187
94395
  } catch (err2) {
94188
94396
  process.stderr.write(source_default.yellow(`warning: mirror to ${dest} failed (${err2.message ?? err2}); ` + `live copy still works, but this skill is not version-controlled until next successful sync.
94189
94397
  `));
@@ -94210,20 +94418,20 @@ function resolveAgent(opts) {
94210
94418
  function resolveAgentsRoot(opts) {
94211
94419
  if (opts.root)
94212
94420
  return resolve55(opts.root);
94213
- return join93(homedir52(), ".switchroom", "agents");
94421
+ return join94(homedir52(), ".switchroom", "agents");
94214
94422
  }
94215
94423
  function personalSkillDir(agentsRoot, agent, name) {
94216
- return join93(agentsRoot, agent, ".claude", "skills", PERSONAL_PREFIX + name);
94424
+ return join94(agentsRoot, agent, ".claude", "skills", PERSONAL_PREFIX + name);
94217
94425
  }
94218
94426
  function trashDir(agentsRoot, agent) {
94219
- return join93(agentsRoot, agent, ".claude", TRASH_DIRNAME);
94427
+ return join94(agentsRoot, agent, ".claude", TRASH_DIRNAME);
94220
94428
  }
94221
94429
  function countPersonalSkills(agentsRoot, agent) {
94222
- const skillsDir = join93(agentsRoot, agent, ".claude", "skills");
94223
- if (!existsSync93(skillsDir))
94430
+ const skillsDir = join94(agentsRoot, agent, ".claude", "skills");
94431
+ if (!existsSync94(skillsDir))
94224
94432
  return 0;
94225
94433
  let n = 0;
94226
- for (const ent of readdirSync35(skillsDir, { withFileTypes: true })) {
94434
+ for (const ent of readdirSync36(skillsDir, { withFileTypes: true })) {
94227
94435
  if (ent.isDirectory() && ent.name.startsWith(PERSONAL_PREFIX))
94228
94436
  n += 1;
94229
94437
  }
@@ -94256,18 +94464,18 @@ function loadFromDir2(dir) {
94256
94464
  }
94257
94465
  const files = {};
94258
94466
  const walk2 = (sub) => {
94259
- for (const ent of readdirSync35(sub, { withFileTypes: true })) {
94260
- const full = join93(sub, ent.name);
94467
+ for (const ent of readdirSync36(sub, { withFileTypes: true })) {
94468
+ const full = join94(sub, ent.name);
94261
94469
  if (ent.isSymbolicLink()) {
94262
- fail4(`refusing to read symlink in --from dir: ${relative3(abs, full)}`);
94470
+ fail4(`refusing to read symlink in --from dir: ${relative5(abs, full)}`);
94263
94471
  }
94264
94472
  if (ent.isDirectory()) {
94265
94473
  walk2(full);
94266
94474
  continue;
94267
94475
  }
94268
94476
  if (ent.isFile()) {
94269
- const rel = relative3(abs, full).replace(/\\/g, "/");
94270
- files[rel] = readFileSync80(full, "utf-8");
94477
+ const rel = relative5(abs, full).replace(/\\/g, "/");
94478
+ files[rel] = readFileSync81(full, "utf-8");
94271
94479
  }
94272
94480
  }
94273
94481
  };
@@ -94310,10 +94518,10 @@ function behavioralValidate(files) {
94310
94518
  errors2.push(`${path9} fails \`bash -n\`: ${(r.stderr ?? "").trim()}`);
94311
94519
  }
94312
94520
  } else if (PY_SCRIPT_RE.test(path9)) {
94313
- const tmp = mkdtempSync6(join93(tmpdir7(), "skill-personal-py-"));
94314
- const tmpPy = join93(tmp, "check.py");
94521
+ const tmp = mkdtempSync6(join94(tmpdir7(), "skill-personal-py-"));
94522
+ const tmpPy = join94(tmp, "check.py");
94315
94523
  try {
94316
- writeFileSync34(tmpPy, content);
94524
+ writeFileSync35(tmpPy, content);
94317
94525
  const r = spawnSync17("python3", ["-m", "py_compile", tmpPy], {
94318
94526
  encoding: "utf-8"
94319
94527
  });
@@ -94329,13 +94537,13 @@ function behavioralValidate(files) {
94329
94537
  }
94330
94538
  function sweepTrash(agentsRoot, agent) {
94331
94539
  const trash = trashDir(agentsRoot, agent);
94332
- if (!existsSync93(trash))
94540
+ if (!existsSync94(trash))
94333
94541
  return;
94334
94542
  const now = Date.now();
94335
- for (const ent of readdirSync35(trash, { withFileTypes: true })) {
94543
+ for (const ent of readdirSync36(trash, { withFileTypes: true })) {
94336
94544
  if (!ent.isDirectory())
94337
94545
  continue;
94338
- const entPath = join93(trash, ent.name);
94546
+ const entPath = join94(trash, ent.name);
94339
94547
  try {
94340
94548
  const st = statSync50(entPath);
94341
94549
  if (now - st.mtimeMs > TRASH_TTL_MS) {
@@ -94355,16 +94563,16 @@ function writePersonalSkill(targetDir, files) {
94355
94563
  if (targetIsSymlink) {
94356
94564
  fail4(`refusing to overwrite symlink at ${targetDir}; investigate manually`);
94357
94565
  }
94358
- mkdirSync53(dirname32(targetDir), { recursive: true, mode: 493 });
94359
- const staging = mkdtempSync6(join93(dirname32(targetDir), `.skill-personal-stage-`));
94566
+ mkdirSync54(dirname34(targetDir), { recursive: true, mode: 493 });
94567
+ const staging = mkdtempSync6(join94(dirname34(targetDir), `.skill-personal-stage-`));
94360
94568
  let oldRename = null;
94361
94569
  try {
94362
94570
  for (const [path9, content] of Object.entries(files)) {
94363
- const full = join93(staging, path9);
94364
- mkdirSync53(dirname32(full), { recursive: true, mode: 493 });
94571
+ const full = join94(staging, path9);
94572
+ mkdirSync54(dirname34(full), { recursive: true, mode: 493 });
94365
94573
  const fd = openSync17(full, "wx");
94366
94574
  try {
94367
- writeFileSync34(fd, content);
94575
+ writeFileSync35(fd, content);
94368
94576
  } finally {
94369
94577
  closeSync17(fd);
94370
94578
  }
@@ -94380,9 +94588,9 @@ function writePersonalSkill(targetDir, files) {
94380
94588
  } catch {}
94381
94589
  if (targetExists) {
94382
94590
  oldRename = `${targetDir}.personal-old-${Date.now()}`;
94383
- renameSync24(targetDir, oldRename);
94591
+ renameSync25(targetDir, oldRename);
94384
94592
  }
94385
- renameSync24(staging, targetDir);
94593
+ renameSync25(staging, targetDir);
94386
94594
  if (oldRename) {
94387
94595
  rmSync19(oldRename, { recursive: true, force: true });
94388
94596
  oldRename = null;
@@ -94391,12 +94599,12 @@ function writePersonalSkill(targetDir, files) {
94391
94599
  try {
94392
94600
  rmSync19(staging, { recursive: true, force: true });
94393
94601
  } catch {}
94394
- if (oldRename && existsSync93(oldRename)) {
94602
+ if (oldRename && existsSync94(oldRename)) {
94395
94603
  try {
94396
- if (existsSync93(targetDir)) {
94604
+ if (existsSync94(targetDir)) {
94397
94605
  rmSync19(targetDir, { recursive: true, force: true });
94398
94606
  }
94399
- renameSync24(oldRename, targetDir);
94607
+ renameSync25(oldRename, targetDir);
94400
94608
  } catch {}
94401
94609
  }
94402
94610
  throw err2;
@@ -94459,7 +94667,7 @@ function loadFiles(opts) {
94459
94667
  return loadFromStdin2();
94460
94668
  }
94461
94669
  const p = resolve55(opts.from);
94462
- if (!existsSync93(p)) {
94670
+ if (!existsSync94(p)) {
94463
94671
  fail4(`--from path does not exist: ${opts.from}`);
94464
94672
  }
94465
94673
  const st = statSync50(p);
@@ -94467,7 +94675,7 @@ function loadFiles(opts) {
94467
94675
  return loadFromDir2(p);
94468
94676
  }
94469
94677
  if (p.endsWith(".md")) {
94470
- return { "SKILL.md": readFileSync80(p, "utf-8") };
94678
+ return { "SKILL.md": readFileSync81(p, "utf-8") };
94471
94679
  }
94472
94680
  fail4(`--from must be a directory or a .md file. Got: ${opts.from}`);
94473
94681
  }
@@ -94507,10 +94715,10 @@ function editPersonalAction(name, opts) {
94507
94715
  }
94508
94716
  var CLONE_SOURCE_RE = /^(shared|bundled):([a-z0-9][a-z0-9_-]{0,62})$/;
94509
94717
  function defaultSharedRoot() {
94510
- return join93(homedir52(), ".switchroom", "skills");
94718
+ return join94(homedir52(), ".switchroom", "skills");
94511
94719
  }
94512
94720
  function defaultBundledRoot() {
94513
- return join93(homedir52(), ".switchroom", "skills", "_bundled");
94721
+ return join94(homedir52(), ".switchroom", "skills", "_bundled");
94514
94722
  }
94515
94723
  function resolveCloneSource(source, opts) {
94516
94724
  const m = CLONE_SOURCE_RE.exec(source);
@@ -94520,8 +94728,8 @@ function resolveCloneSource(source, opts) {
94520
94728
  const tier = m[1];
94521
94729
  const slug = m[2];
94522
94730
  const root = tier === "bundled" ? opts.bundledRoot ?? defaultBundledRoot() : opts.sharedRoot ?? defaultSharedRoot();
94523
- const dir = join93(root, slug);
94524
- if (!existsSync93(dir)) {
94731
+ const dir = join94(root, slug);
94732
+ if (!existsSync94(dir)) {
94525
94733
  fail4(`clone source ${JSON.stringify(source)} not found at ${dir}; ` + `check \`switchroom skill search --tier ${tier}\``, 1);
94526
94734
  }
94527
94735
  const st = lstatSync12(dir);
@@ -94535,8 +94743,8 @@ function readSourceFiles(dir) {
94535
94743
  const files = {};
94536
94744
  const skipped = [];
94537
94745
  const walk2 = (sub) => {
94538
- for (const ent of readdirSync35(sub, { withFileTypes: true })) {
94539
- const full = join93(sub, ent.name);
94746
+ for (const ent of readdirSync36(sub, { withFileTypes: true })) {
94747
+ const full = join94(sub, ent.name);
94540
94748
  if (ent.isSymbolicLink()) {
94541
94749
  continue;
94542
94750
  }
@@ -94545,7 +94753,7 @@ function readSourceFiles(dir) {
94545
94753
  continue;
94546
94754
  }
94547
94755
  if (ent.isFile()) {
94548
- const rel = relative3(dir, full).replace(/\\/g, "/");
94756
+ const rel = relative5(dir, full).replace(/\\/g, "/");
94549
94757
  if (!validateRelPath(rel)) {
94550
94758
  skipped.push(rel);
94551
94759
  continue;
@@ -94556,7 +94764,7 @@ function readSourceFiles(dir) {
94556
94764
  fail4(`clone source has oversized file ${rel} (${st.size} bytes > ${CLONE_MAX_FILE_BYTES}); ` + `refuse to read`, 3);
94557
94765
  }
94558
94766
  } catch {}
94559
- files[rel] = readFileSync80(full, "utf-8");
94767
+ files[rel] = readFileSync81(full, "utf-8");
94560
94768
  }
94561
94769
  }
94562
94770
  };
@@ -94645,10 +94853,10 @@ function removePersonalAction(name, opts) {
94645
94853
  throw err2;
94646
94854
  }
94647
94855
  const trashRoot2 = trashDir(agentsRoot, agent);
94648
- mkdirSync53(trashRoot2, { recursive: true, mode: 493 });
94856
+ mkdirSync54(trashRoot2, { recursive: true, mode: 493 });
94649
94857
  const ts = Date.now();
94650
- const trashTarget = join93(trashRoot2, `${name}-${ts}`);
94651
- renameSync24(target, trashTarget);
94858
+ const trashTarget = join94(trashRoot2, `${name}-${ts}`);
94859
+ renameSync25(target, trashTarget);
94652
94860
  const now = new Date(ts);
94653
94861
  utimesSync(trashTarget, now, now);
94654
94862
  mirrorToConfigRepo(agent, name, null);
@@ -94666,27 +94874,27 @@ function listPersonalAction(opts) {
94666
94874
  const agent = resolveAgent(opts);
94667
94875
  const agentsRoot = resolveAgentsRoot(opts);
94668
94876
  sweepTrash(agentsRoot, agent);
94669
- const skillsDir = join93(agentsRoot, agent, ".claude", "skills");
94877
+ const skillsDir = join94(agentsRoot, agent, ".claude", "skills");
94670
94878
  const personal = [];
94671
- if (existsSync93(skillsDir)) {
94672
- for (const ent of readdirSync35(skillsDir, { withFileTypes: true })) {
94879
+ if (existsSync94(skillsDir)) {
94880
+ for (const ent of readdirSync36(skillsDir, { withFileTypes: true })) {
94673
94881
  if (!ent.isDirectory())
94674
94882
  continue;
94675
94883
  if (!ent.name.startsWith(PERSONAL_PREFIX))
94676
94884
  continue;
94677
94885
  const skillName = ent.name.slice(PERSONAL_PREFIX.length);
94678
- const skillPath = join93(skillsDir, ent.name);
94886
+ const skillPath = join94(skillsDir, ent.name);
94679
94887
  let fileCount = 0;
94680
94888
  let totalBytes = 0;
94681
94889
  const walk2 = (sub) => {
94682
- for (const e of readdirSync35(sub, { withFileTypes: true })) {
94890
+ for (const e of readdirSync36(sub, { withFileTypes: true })) {
94683
94891
  if (e.isFile()) {
94684
94892
  fileCount += 1;
94685
94893
  try {
94686
- totalBytes += statSync50(join93(sub, e.name)).size;
94894
+ totalBytes += statSync50(join94(sub, e.name)).size;
94687
94895
  } catch {}
94688
94896
  } else if (e.isDirectory()) {
94689
- walk2(join93(sub, e.name));
94897
+ walk2(join94(sub, e.name));
94690
94898
  }
94691
94899
  }
94692
94900
  };
@@ -94725,11 +94933,11 @@ function registerSkillPersonalCommands(program3) {
94725
94933
  // src/cli/self-improve-propose-skill.ts
94726
94934
  import { createConnection as createConnection4 } from "node:net";
94727
94935
  import { homedir as homedir53 } from "node:os";
94728
- import { join as join94 } from "node:path";
94729
- import { readFileSync as readFileSync81 } from "node:fs";
94936
+ import { join as join95 } from "node:path";
94937
+ import { readFileSync as readFileSync82 } from "node:fs";
94730
94938
  var IPC_CONNECT_TIMEOUT_MS = 5000;
94731
94939
  function gatewaySocketPath() {
94732
- return process.env.SWITCHROOM_GATEWAY_SOCKET ?? (process.env.TELEGRAM_STATE_DIR ? join94(process.env.TELEGRAM_STATE_DIR, "gateway.sock") : join94(homedir53(), ".claude", "channels", "telegram", "gateway.sock"));
94940
+ return process.env.SWITCHROOM_GATEWAY_SOCKET ?? (process.env.TELEGRAM_STATE_DIR ? join95(process.env.TELEGRAM_STATE_DIR, "gateway.sock") : join95(homedir53(), ".claude", "channels", "telegram", "gateway.sock"));
94733
94941
  }
94734
94942
  function fail5(msg, code = 1) {
94735
94943
  console.error(msg);
@@ -94764,7 +94972,7 @@ function registerSelfImproveProposeSkillCommand(program3) {
94764
94972
  fail5("agent name required (--agent or $SWITCHROOM_AGENT_NAME)");
94765
94973
  let draft;
94766
94974
  try {
94767
- draft = JSON.parse(readFileSync81(opts.draft, "utf-8"));
94975
+ draft = JSON.parse(readFileSync82(opts.draft, "utf-8"));
94768
94976
  } catch (e) {
94769
94977
  fail5(`failed to read/parse --draft: ${e.message}`);
94770
94978
  }
@@ -94801,9 +95009,9 @@ function registerSelfImproveProposeSkillCommand(program3) {
94801
95009
  init_esm();
94802
95010
  init_helpers();
94803
95011
  var import_yaml25 = __toESM(require_dist(), 1);
94804
- import { existsSync as existsSync94, readdirSync as readdirSync36, readFileSync as readFileSync82, statSync as statSync51 } from "node:fs";
95012
+ import { existsSync as existsSync95, readdirSync as readdirSync37, readFileSync as readFileSync83, statSync as statSync51 } from "node:fs";
94805
95013
  import { homedir as homedir54 } from "node:os";
94806
- import { join as join95, resolve as resolve56 } from "node:path";
95014
+ import { join as join96, resolve as resolve56 } from "node:path";
94807
95015
  var PERSONAL_PREFIX2 = "personal-";
94808
95016
  var BUNDLED_SUBDIR = "_bundled";
94809
95017
  var AGENT_NAME_RE3 = /^[a-z][a-z0-9_-]{0,62}$/;
@@ -94817,12 +95025,12 @@ function defaultBundledRoot2() {
94817
95025
  return resolve56(homedir54(), ".switchroom/skills/_bundled");
94818
95026
  }
94819
95027
  function readSkillFrontmatter(skillDir) {
94820
- const mdPath = join95(skillDir, "SKILL.md");
94821
- if (!existsSync94(mdPath))
95028
+ const mdPath = join96(skillDir, "SKILL.md");
95029
+ if (!existsSync95(mdPath))
94822
95030
  return null;
94823
95031
  let content;
94824
95032
  try {
94825
- content = readFileSync82(mdPath, "utf-8");
95033
+ content = readFileSync83(mdPath, "utf-8");
94826
95034
  } catch {
94827
95035
  return null;
94828
95036
  }
@@ -94850,7 +95058,7 @@ function readSkillFrontmatter(skillDir) {
94850
95058
  return { fm: parsed };
94851
95059
  }
94852
95060
  function statSkillMd(skillDir) {
94853
- const mdPath = join95(skillDir, "SKILL.md");
95061
+ const mdPath = join96(skillDir, "SKILL.md");
94854
95062
  try {
94855
95063
  const st = statSync51(mdPath);
94856
95064
  return { size: st.size, mtime: st.mtime.toISOString() };
@@ -94861,20 +95069,20 @@ function statSkillMd(skillDir) {
94861
95069
  function listPersonalSkills(agent, agentsRoot = defaultAgentsRoot()) {
94862
95070
  if (!AGENT_NAME_RE3.test(agent))
94863
95071
  return [];
94864
- const skillsDir = join95(agentsRoot, agent, ".claude/skills");
94865
- if (!existsSync94(skillsDir))
95072
+ const skillsDir = join96(agentsRoot, agent, ".claude/skills");
95073
+ if (!existsSync95(skillsDir))
94866
95074
  return [];
94867
95075
  const out = [];
94868
95076
  let entries;
94869
95077
  try {
94870
- entries = readdirSync36(skillsDir);
95078
+ entries = readdirSync37(skillsDir);
94871
95079
  } catch {
94872
95080
  return [];
94873
95081
  }
94874
95082
  for (const ent of entries) {
94875
95083
  if (!ent.startsWith(PERSONAL_PREFIX2))
94876
95084
  continue;
94877
- const dirPath = join95(skillsDir, ent);
95085
+ const dirPath = join96(skillsDir, ent);
94878
95086
  try {
94879
95087
  if (!statSync51(dirPath).isDirectory())
94880
95088
  continue;
@@ -94900,12 +95108,12 @@ function listPersonalSkills(agent, agentsRoot = defaultAgentsRoot()) {
94900
95108
  return out;
94901
95109
  }
94902
95110
  function listSharedSkills(sharedRoot = defaultSharedRoot2()) {
94903
- if (!existsSync94(sharedRoot))
95111
+ if (!existsSync95(sharedRoot))
94904
95112
  return [];
94905
95113
  const out = [];
94906
95114
  let entries;
94907
95115
  try {
94908
- entries = readdirSync36(sharedRoot);
95116
+ entries = readdirSync37(sharedRoot);
94909
95117
  } catch {
94910
95118
  return [];
94911
95119
  }
@@ -94914,7 +95122,7 @@ function listSharedSkills(sharedRoot = defaultSharedRoot2()) {
94914
95122
  continue;
94915
95123
  if (ent.startsWith("."))
94916
95124
  continue;
94917
- const dirPath = join95(sharedRoot, ent);
95125
+ const dirPath = join96(sharedRoot, ent);
94918
95126
  try {
94919
95127
  if (!statSync51(dirPath).isDirectory())
94920
95128
  continue;
@@ -94938,19 +95146,19 @@ function listSharedSkills(sharedRoot = defaultSharedRoot2()) {
94938
95146
  return out;
94939
95147
  }
94940
95148
  function listBundledSkills(bundledRoot = defaultBundledRoot2()) {
94941
- if (!existsSync94(bundledRoot))
95149
+ if (!existsSync95(bundledRoot))
94942
95150
  return [];
94943
95151
  const out = [];
94944
95152
  let entries;
94945
95153
  try {
94946
- entries = readdirSync36(bundledRoot);
95154
+ entries = readdirSync37(bundledRoot);
94947
95155
  } catch {
94948
95156
  return [];
94949
95157
  }
94950
95158
  for (const ent of entries) {
94951
95159
  if (ent.startsWith("."))
94952
95160
  continue;
94953
- const dirPath = join95(bundledRoot, ent);
95161
+ const dirPath = join96(bundledRoot, ent);
94954
95162
  try {
94955
95163
  if (!statSync51(dirPath).isDirectory())
94956
95164
  continue;
@@ -95096,18 +95304,18 @@ init_source();
95096
95304
  init_helpers();
95097
95305
  init_operator_uid();
95098
95306
  import {
95099
- existsSync as existsSync96,
95100
- mkdirSync as mkdirSync54,
95101
- readdirSync as readdirSync37,
95102
- readFileSync as readFileSync84,
95103
- writeFileSync as writeFileSync35,
95307
+ existsSync as existsSync97,
95308
+ mkdirSync as mkdirSync55,
95309
+ readdirSync as readdirSync38,
95310
+ readFileSync as readFileSync85,
95311
+ writeFileSync as writeFileSync36,
95104
95312
  statSync as statSync52,
95105
95313
  lstatSync as lstatSync13,
95106
95314
  realpathSync as realpathSync8,
95107
95315
  copyFileSync as copyFileSync13
95108
95316
  } from "node:fs";
95109
95317
  import { homedir as homedir55 } from "node:os";
95110
- import { join as join96 } from "node:path";
95318
+ import { join as join97 } from "node:path";
95111
95319
  import { spawnSync as spawnSync20 } from "node:child_process";
95112
95320
 
95113
95321
  // src/cli/singleton-stale-cleanup.ts
@@ -95456,7 +95664,7 @@ function resolveHostdHostHome(env2 = process.env, home2 = homedir55()) {
95456
95664
  return resolved;
95457
95665
  }
95458
95666
  function resolveHostdSkillsTarget(hostHome) {
95459
- const skillsPath = join96(hostHome, ".switchroom", "skills");
95667
+ const skillsPath = join97(hostHome, ".switchroom", "skills");
95460
95668
  let st;
95461
95669
  try {
95462
95670
  st = lstatSync13(skillsPath);
@@ -95473,21 +95681,21 @@ function resolveHostdSkillsTarget(hostHome) {
95473
95681
  console.warn(`switchroom hostd install: ~/.switchroom/skills is a symlink whose target ` + `does not resolve (dangling) \u2014 skipping the skills bind mount. Bundled ` + `skills will be unavailable to rollout/update until the symlink is fixed.`);
95474
95682
  return;
95475
95683
  }
95476
- if (!existsSync96(target)) {
95684
+ if (!existsSync97(target)) {
95477
95685
  console.warn(`switchroom hostd install: ~/.switchroom/skills resolves to "${target}", ` + `which does not exist \u2014 skipping the skills bind mount. Bundled skills ` + `will be unavailable to rollout/update until the symlink target exists.`);
95478
95686
  return;
95479
95687
  }
95480
95688
  return target;
95481
95689
  }
95482
95690
  function hostdDir() {
95483
- return join96(homedir55(), ".switchroom", "hostd");
95691
+ return join97(homedir55(), ".switchroom", "hostd");
95484
95692
  }
95485
95693
  function hostdComposePath() {
95486
- return join96(hostdDir(), "docker-compose.yml");
95694
+ return join97(hostdDir(), "docker-compose.yml");
95487
95695
  }
95488
95696
  function backupExistingCompose() {
95489
95697
  const p = hostdComposePath();
95490
- if (!existsSync96(p))
95698
+ if (!existsSync97(p))
95491
95699
  return null;
95492
95700
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
95493
95701
  const bak = `${p}.bak-${ts}`;
@@ -95520,7 +95728,7 @@ async function doInstall(opts, program3) {
95520
95728
  }
95521
95729
  const dir = hostdDir();
95522
95730
  const composePath = hostdComposePath();
95523
- mkdirSync54(dir, { recursive: true });
95731
+ mkdirSync55(dir, { recursive: true });
95524
95732
  const imageTag = resolveHostdImageTag(opts.tag, cfg.release);
95525
95733
  const guard = checkDowngrade({
95526
95734
  container: "switchroom-hostd",
@@ -95553,7 +95761,7 @@ async function doInstall(opts, program3) {
95553
95761
  const bak = backupExistingCompose();
95554
95762
  if (bak)
95555
95763
  console.log(source_default.dim(` Backed up existing compose to ${bak}`));
95556
- writeFileSync35(composePath, yaml, "utf8");
95764
+ writeFileSync36(composePath, yaml, "utf8");
95557
95765
  console.log(source_default.green(` \u2713 Wrote ${composePath}`));
95558
95766
  const adminAgents = Object.entries(cfg.agents ?? {}).filter(([, a]) => a?.admin === true).map(([name]) => name);
95559
95767
  console.log(source_default.dim(` agents served (one socket each): ${allAgents.length === 0 ? "(none)" : allAgents.join(", ")}`));
@@ -95585,7 +95793,7 @@ function doStatus() {
95585
95793
  const composeYml = hostdComposePath();
95586
95794
  console.log(source_default.bold("switchroom-hostd"));
95587
95795
  console.log("");
95588
- if (!existsSync96(composeYml)) {
95796
+ if (!existsSync97(composeYml)) {
95589
95797
  console.log(source_default.yellow(" compose: not installed"));
95590
95798
  console.log(source_default.dim(" run `switchroom hostd install` to set up."));
95591
95799
  return;
@@ -95606,14 +95814,14 @@ function doStatus() {
95606
95814
  } else {
95607
95815
  console.log(source_default.green(` container: ${ps.stdout.trim()}`));
95608
95816
  }
95609
- if (existsSync96(dir)) {
95817
+ if (existsSync97(dir)) {
95610
95818
  const entries = [];
95611
95819
  try {
95612
- for (const name of readdirSync37(dir)) {
95820
+ for (const name of readdirSync38(dir)) {
95613
95821
  if (name === "docker-compose.yml" || name.startsWith("docker-compose.yml."))
95614
95822
  continue;
95615
- const sockPath = join96(dir, name, "sock");
95616
- if (existsSync96(sockPath)) {
95823
+ const sockPath = join97(dir, name, "sock");
95824
+ if (existsSync97(sockPath)) {
95617
95825
  const st = statSync52(sockPath);
95618
95826
  if ((st.mode & 61440) === 49152) {
95619
95827
  entries.push(`${name} \u2192 ${sockPath}`);
@@ -95632,7 +95840,7 @@ function doStatus() {
95632
95840
  }
95633
95841
  function doUninstall() {
95634
95842
  const composeYml = hostdComposePath();
95635
- if (!existsSync96(composeYml)) {
95843
+ if (!existsSync97(composeYml)) {
95636
95844
  console.log(source_default.yellow(" No hostd install detected (no compose file at this path)."));
95637
95845
  return;
95638
95846
  }
@@ -95656,12 +95864,12 @@ function registerHostdCommand(program3) {
95656
95864
  hostd.command("uninstall").description("Stop the hostd container. Leaves the compose file in place for re-install.").action(() => doUninstall());
95657
95865
  hostd.command("audit").description("Tail and filter the hostd audit log (privileged-verb call history)").option("--tail <n>", "Number of matching entries to show (default: 50)", "50").option("--agent <name>", "Filter to a specific caller agent").option("--op <verb>", "Filter to a specific hostd verb (e.g. update_apply, agent_restart)").option("--error", "Show only failed (error/denied) entries").option("--verbose", "Show the captured stderr / error tail under each failed row").option("--path <file>", "Override audit log path (for debugging)").action((opts) => {
95658
95866
  const logPath = opts.path ?? defaultAuditLogPath2();
95659
- if (!existsSync96(logPath)) {
95867
+ if (!existsSync97(logPath)) {
95660
95868
  console.error(source_default.yellow(`Audit log not found at ${logPath}.`) + source_default.gray(`
95661
95869
  The log is created when hostd handles its first privileged-verb request.`));
95662
95870
  return;
95663
95871
  }
95664
- const raw = readFileSync84(logPath, "utf-8");
95872
+ const raw = readFileSync85(logPath, "utf-8");
95665
95873
  const limit = Math.max(1, parseInt(opts.tail ?? "50", 10) || 50);
95666
95874
  const filters = {
95667
95875
  agent: opts.agent,
@@ -95704,9 +95912,9 @@ The log is created when hostd handles its first privileged-verb request.`));
95704
95912
  init_source();
95705
95913
  init_helpers();
95706
95914
  init_operator_uid();
95707
- import { chownSync as chownSync9, existsSync as existsSync97, mkdirSync as mkdirSync55, writeFileSync as writeFileSync36, copyFileSync as copyFileSync14 } from "node:fs";
95915
+ import { chownSync as chownSync9, existsSync as existsSync98, mkdirSync as mkdirSync56, writeFileSync as writeFileSync37, copyFileSync as copyFileSync14 } from "node:fs";
95708
95916
  import { homedir as homedir56 } from "node:os";
95709
- import { join as join97 } from "node:path";
95917
+ import { join as join98 } from "node:path";
95710
95918
  import { spawnSync as spawnSync21 } from "node:child_process";
95711
95919
  function resolveWebImageTag(explicitTag, release) {
95712
95920
  if (explicitTag)
@@ -95806,14 +96014,14 @@ services:
95806
96014
  `;
95807
96015
  }
95808
96016
  function webdDir() {
95809
- return join97(homedir56(), ".switchroom", "web");
96017
+ return join98(homedir56(), ".switchroom", "web");
95810
96018
  }
95811
96019
  function webdComposePath() {
95812
- return join97(webdDir(), "docker-compose.yml");
96020
+ return join98(webdDir(), "docker-compose.yml");
95813
96021
  }
95814
96022
  function backupExistingCompose2() {
95815
96023
  const p = webdComposePath();
95816
- if (!existsSync97(p))
96024
+ if (!existsSync98(p))
95817
96025
  return null;
95818
96026
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
95819
96027
  const bak = `${p}.bak-${ts}`;
@@ -95838,7 +96046,7 @@ async function doInstall2(opts, program3) {
95838
96046
  }
95839
96047
  const dir = webdDir();
95840
96048
  const composePath = webdComposePath();
95841
- mkdirSync55(dir, { recursive: true });
96049
+ mkdirSync56(dir, { recursive: true });
95842
96050
  const cfg = getConfig(program3);
95843
96051
  const imageTag = resolveWebImageTag(opts.tag, cfg.release);
95844
96052
  const port = cfg.web_service?.port ?? 8080;
@@ -95873,7 +96081,7 @@ async function doInstall2(opts, program3) {
95873
96081
  const bak = backupExistingCompose2();
95874
96082
  if (bak)
95875
96083
  console.log(source_default.dim(` Backed up existing compose to ${bak}`));
95876
- writeFileSync36(composePath, yaml, "utf8");
96084
+ writeFileSync37(composePath, yaml, "utf8");
95877
96085
  try {
95878
96086
  if (typeof process.geteuid === "function" && process.geteuid() === 0) {
95879
96087
  chownSync9(dir, operatorUid, operatorUid);
@@ -95915,7 +96123,7 @@ function doStatus2() {
95915
96123
  const composeYml = webdComposePath();
95916
96124
  console.log(source_default.bold("switchroom-web"));
95917
96125
  console.log("");
95918
- if (!existsSync97(composeYml)) {
96126
+ if (!existsSync98(composeYml)) {
95919
96127
  console.log(source_default.yellow(" compose: not installed"));
95920
96128
  console.log(source_default.dim(" run `switchroom webd install` to set up."));
95921
96129
  return;
@@ -95939,7 +96147,7 @@ function doStatus2() {
95939
96147
  }
95940
96148
  function doUninstall2() {
95941
96149
  const composeYml = webdComposePath();
95942
- if (!existsSync97(composeYml)) {
96150
+ if (!existsSync98(composeYml)) {
95943
96151
  console.log(source_default.yellow(" No web-service install detected (no compose file at this path)."));
95944
96152
  return;
95945
96153
  }
@@ -95969,9 +96177,9 @@ function registerWebdCommand(program3) {
95969
96177
  // src/cli/host-repair.ts
95970
96178
  init_source();
95971
96179
  import { homedir as homedir57 } from "node:os";
95972
- import { join as join98 } from "node:path";
96180
+ import { join as join99 } from "node:path";
95973
96181
  var ARTIFACT_ALLOWLIST = {
95974
- dockerComposePluginDir: (home2) => join98(home2, ".docker", "cli-plugins", "docker-compose"),
96182
+ dockerComposePluginDir: (home2) => join99(home2, ".docker", "cli-plugins", "docker-compose"),
95975
96183
  stateSentinel: "/state"
95976
96184
  };
95977
96185
  function isStateBogusAutoDir(probe2) {
@@ -96125,7 +96333,7 @@ function applyMountRepairs(items, deps) {
96125
96333
  function registerHostCommand(program3) {
96126
96334
  const host = program3.command("host").description("Host-level maintenance operations for switchroom");
96127
96335
  host.command("repair-mounts").description("Detect and remove known auto-dir artifacts left by a container-context deploy " + "(2026-06-23 outage class). Default: dry-run. Pass --yes to apply.").option("--yes", "Actually perform the removals (default is dry-run)").action(async (opts) => {
96128
- const { rmdirSync: rmdirSync2, rmSync: rmSync20, lstatSync: lstatSync14, readdirSync: readdirSync38 } = await import("node:fs");
96336
+ const { rmdirSync: rmdirSync2, rmSync: rmSync20, lstatSync: lstatSync14, readdirSync: readdirSync39 } = await import("node:fs");
96129
96337
  const probe2 = {
96130
96338
  lstat(path9) {
96131
96339
  try {
@@ -96136,7 +96344,7 @@ function registerHostCommand(program3) {
96136
96344
  },
96137
96345
  readdir(path9) {
96138
96346
  try {
96139
- return readdirSync38(path9);
96347
+ return readdirSync39(path9);
96140
96348
  } catch {
96141
96349
  return null;
96142
96350
  }