switchroom 0.14.92 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -23137,42 +23137,6 @@ var init_resolver = __esm(() => {
23137
23137
  materializedDirs = new Set;
23138
23138
  });
23139
23139
 
23140
- // src/agents/tmux.ts
23141
- import { execFileSync as execFileSync5 } from "node:child_process";
23142
- function sendAgentInterrupt(opts) {
23143
- const { agentName } = opts;
23144
- const attempts = typeof opts.attempts === "number" && opts.attempts > 0 ? opts.attempts : 1;
23145
- const retryDelayMs = typeof opts.retryDelayMs === "number" && opts.retryDelayMs >= 0 ? opts.retryDelayMs : 100;
23146
- const socket = `switchroom-${agentName}`;
23147
- const args = ["-L", socket, "send-keys", "-t", agentName, "C-c"];
23148
- let lastError = null;
23149
- for (let i = 0;i < attempts; i++) {
23150
- try {
23151
- execFileSync5("tmux", args, {
23152
- timeout: 3000,
23153
- stdio: ["ignore", "pipe", "pipe"]
23154
- });
23155
- return { ok: true };
23156
- } catch (err) {
23157
- lastError = `tmux send-keys C-c failed: ${err.message}`;
23158
- console.error(`[tmux-interrupt] ${agentName}: ${lastError}`);
23159
- }
23160
- if (i < attempts - 1 && retryDelayMs > 0) {
23161
- sleepSync(retryDelayMs);
23162
- }
23163
- }
23164
- return { error: lastError ?? "tmux send-keys C-c failed" };
23165
- }
23166
- function sleepSync(ms) {
23167
- const sab = new SharedArrayBuffer(4);
23168
- const view = new Int32Array(sab);
23169
- Atomics.wait(view, 0, 0, ms);
23170
- }
23171
- var MAX_BYTES;
23172
- var init_tmux = __esm(() => {
23173
- MAX_BYTES = 10 * 1024 * 1024;
23174
- });
23175
-
23176
23140
  // src/agents/compose.ts
23177
23141
  import { createHash as createHash3 } from "node:crypto";
23178
23142
  import { existsSync as existsSync14, mkdirSync as mkdirSync10, readFileSync as readFileSync12 } from "node:fs";
@@ -23804,10 +23768,46 @@ var init_compose = __esm(() => {
23804
23768
  BIND_MOUNT_EXACT_SOURCE_DENY = new Set(["/var/run/docker.sock"]);
23805
23769
  });
23806
23770
 
23771
+ // src/agents/tmux.ts
23772
+ import { execFileSync as execFileSync5 } from "node:child_process";
23773
+ function sendAgentInterrupt(opts) {
23774
+ const { agentName } = opts;
23775
+ const attempts = typeof opts.attempts === "number" && opts.attempts > 0 ? opts.attempts : 1;
23776
+ const retryDelayMs = typeof opts.retryDelayMs === "number" && opts.retryDelayMs >= 0 ? opts.retryDelayMs : 100;
23777
+ const socket = `switchroom-${agentName}`;
23778
+ const args = ["-L", socket, "send-keys", "-t", agentName, "C-c"];
23779
+ let lastError = null;
23780
+ for (let i = 0;i < attempts; i++) {
23781
+ try {
23782
+ execFileSync5("tmux", args, {
23783
+ timeout: 3000,
23784
+ stdio: ["ignore", "pipe", "pipe"]
23785
+ });
23786
+ return { ok: true };
23787
+ } catch (err) {
23788
+ lastError = `tmux send-keys C-c failed: ${err.message}`;
23789
+ console.error(`[tmux-interrupt] ${agentName}: ${lastError}`);
23790
+ }
23791
+ if (i < attempts - 1 && retryDelayMs > 0) {
23792
+ sleepSync(retryDelayMs);
23793
+ }
23794
+ }
23795
+ return { error: lastError ?? "tmux send-keys C-c failed" };
23796
+ }
23797
+ function sleepSync(ms) {
23798
+ const sab = new SharedArrayBuffer(4);
23799
+ const view = new Int32Array(sab);
23800
+ Atomics.wait(view, 0, 0, ms);
23801
+ }
23802
+ var MAX_BYTES;
23803
+ var init_tmux = __esm(() => {
23804
+ MAX_BYTES = 10 * 1024 * 1024;
23805
+ });
23806
+
23807
23807
  // src/agents/docker-fleet.ts
23808
23808
  import { resolve as resolve12 } from "node:path";
23809
23809
  import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync6 } from "node:fs";
23810
- import { homedir as homedir5 } from "node:os";
23810
+ import { homedir as homedir6 } from "node:os";
23811
23811
  import { execFileSync as execFileSync6 } from "node:child_process";
23812
23812
  function resolveSwitchroomHome(explicit) {
23813
23813
  if (explicit && explicit.length > 0)
@@ -23831,7 +23831,7 @@ function bringUpAgentService(opts) {
23831
23831
  }
23832
23832
  const compose = opts.generateComposeContent?.() ?? generateCompose({
23833
23833
  config: opts.config,
23834
- homeDir: homedir5(),
23834
+ homeDir: homedir6(),
23835
23835
  switchroomConfigPath
23836
23836
  });
23837
23837
  const composePath = resolve12(composeDir, "docker-compose.yml");
@@ -23952,18 +23952,18 @@ var init_singleton_reconcile = __esm(() => {
23952
23952
 
23953
23953
  // src/agents/lifecycle.ts
23954
23954
  import { execFileSync as execFileSync8, spawn, spawnSync } from "node:child_process";
23955
- import { existsSync as existsSync15, mkdirSync as mkdirSync12, writeFileSync as writeFileSync7, renameSync as renameSync4, readFileSync as readFileSync14 } from "node:fs";
23956
- import { resolve as resolve13, join as join10 } from "node:path";
23955
+ import { existsSync as existsSync16, mkdirSync as mkdirSync12, writeFileSync as writeFileSync7, renameSync as renameSync4, readFileSync as readFileSync14 } from "node:fs";
23956
+ import { resolve as resolve13, join as join11 } from "node:path";
23957
23957
  import { connect } from "node:net";
23958
23958
  function cleanShutdownMarkerPathForAgent(name) {
23959
23959
  const agentsDir = process.env.SWITCHROOM_AGENTS_DIR ?? resolveStatePath("agents");
23960
- return join10(agentsDir, name, "telegram", "clean-shutdown.json");
23960
+ return join11(agentsDir, name, "telegram", "clean-shutdown.json");
23961
23961
  }
23962
23962
  function writeRestartReasonMarker(name, reason, opts = {}) {
23963
23963
  const path = cleanShutdownMarkerPathForAgent(name);
23964
23964
  try {
23965
- mkdirSync12(join10(path, ".."), { recursive: true });
23966
- if (opts.preserveExisting && existsSync15(path)) {
23965
+ mkdirSync12(join11(path, ".."), { recursive: true });
23966
+ if (opts.preserveExisting && existsSync16(path)) {
23967
23967
  try {
23968
23968
  const prev = JSON.parse(readFileSync14(path, "utf-8"));
23969
23969
  if (prev && typeof prev.ts === "number" && Date.now() - prev.ts < 30000 && prev.reason) {
@@ -24066,8 +24066,8 @@ function gracefulRestartAgent(name) {
24066
24066
  return new Promise((resolvePromise, reject) => {
24067
24067
  const agentsDir = process.env.SWITCHROOM_AGENTS_DIR ?? resolveStatePath("agents");
24068
24068
  const agentDir = resolve13(agentsDir, name);
24069
- const socketPath = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join10(agentDir, "telegram", "gateway.sock");
24070
- if (!existsSync15(socketPath)) {
24069
+ const socketPath = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join11(agentDir, "telegram", "gateway.sock");
24070
+ if (!existsSync16(socketPath)) {
24071
24071
  reject(new Error("Gateway socket not found. Is the gateway running?"));
24072
24072
  return;
24073
24073
  }
@@ -24452,40 +24452,40 @@ var init_pane_ready_probe = () => {};
24452
24452
  // src/auth/accounts.ts
24453
24453
  import {
24454
24454
  copyFileSync as copyFileSync5,
24455
- existsSync as existsSync19,
24455
+ existsSync as existsSync20,
24456
24456
  mkdirSync as mkdirSync14,
24457
24457
  readFileSync as readFileSync18,
24458
- readdirSync as readdirSync9,
24458
+ readdirSync as readdirSync10,
24459
24459
  renameSync as renameSync6,
24460
24460
  rmSync as rmSync4,
24461
- statSync as statSync11,
24461
+ statSync as statSync12,
24462
24462
  writeFileSync as writeFileSync9
24463
24463
  } from "node:fs";
24464
24464
  import { randomBytes as randomBytes2 } from "node:crypto";
24465
- import { join as join13 } from "node:path";
24465
+ import { join as join14 } from "node:path";
24466
24466
  function claudeDir(agentDir) {
24467
- return join13(agentDir, ".claude");
24467
+ return join14(agentDir, ".claude");
24468
24468
  }
24469
24469
  function accountsDir(agentDir) {
24470
- return join13(claudeDir(agentDir), "accounts");
24470
+ return join14(claudeDir(agentDir), "accounts");
24471
24471
  }
24472
24472
  function slotDir(agentDir, slot) {
24473
- return join13(accountsDir(agentDir), slot);
24473
+ return join14(accountsDir(agentDir), slot);
24474
24474
  }
24475
24475
  function slotTokenPath(agentDir, slot) {
24476
- return join13(slotDir(agentDir, slot), ".oauth-token");
24476
+ return join14(slotDir(agentDir, slot), ".oauth-token");
24477
24477
  }
24478
24478
  function slotMetaPath(agentDir, slot) {
24479
- return join13(slotDir(agentDir, slot), ".oauth-token.meta.json");
24479
+ return join14(slotDir(agentDir, slot), ".oauth-token.meta.json");
24480
24480
  }
24481
24481
  function activeMarkerPath(agentDir) {
24482
- return join13(claudeDir(agentDir), "active");
24482
+ return join14(claudeDir(agentDir), "active");
24483
24483
  }
24484
24484
  function legacyTokenPath(agentDir) {
24485
- return join13(claudeDir(agentDir), ".oauth-token");
24485
+ return join14(claudeDir(agentDir), ".oauth-token");
24486
24486
  }
24487
24487
  function legacyMetaPath(agentDir) {
24488
- return join13(claudeDir(agentDir), ".oauth-token.meta.json");
24488
+ return join14(claudeDir(agentDir), ".oauth-token.meta.json");
24489
24489
  }
24490
24490
  function validateSlotName(slot) {
24491
24491
  if (typeof slot !== "string" || slot.length === 0) {
@@ -24506,7 +24506,7 @@ function validateSlotName(slot) {
24506
24506
  }
24507
24507
  function readActiveSlot(agentDir) {
24508
24508
  const p = activeMarkerPath(agentDir);
24509
- if (!existsSync19(p))
24509
+ if (!existsSync20(p))
24510
24510
  return null;
24511
24511
  try {
24512
24512
  const val = readFileSync18(p, "utf-8").trim();
@@ -24523,12 +24523,12 @@ function writeActiveSlot(agentDir, slot) {
24523
24523
  }
24524
24524
  function listSlots(agentDir) {
24525
24525
  const dir = accountsDir(agentDir);
24526
- if (!existsSync19(dir))
24526
+ if (!existsSync20(dir))
24527
24527
  return [];
24528
24528
  try {
24529
- return readdirSync9(dir).filter((name) => {
24529
+ return readdirSync10(dir).filter((name) => {
24530
24530
  try {
24531
- return statSync11(join13(dir, name)).isDirectory();
24531
+ return statSync12(join14(dir, name)).isDirectory();
24532
24532
  } catch {
24533
24533
  return false;
24534
24534
  }
@@ -24538,11 +24538,11 @@ function listSlots(agentDir) {
24538
24538
  }
24539
24539
  }
24540
24540
  function slotExists(agentDir, slot) {
24541
- return existsSync19(slotTokenPath(agentDir, slot));
24541
+ return existsSync20(slotTokenPath(agentDir, slot));
24542
24542
  }
24543
24543
  function readSlotMeta(agentDir, slot) {
24544
24544
  const p = slotMetaPath(agentDir, slot);
24545
- if (!existsSync19(p))
24545
+ if (!existsSync20(p))
24546
24546
  return null;
24547
24547
  try {
24548
24548
  return JSON.parse(readFileSync18(p, "utf-8"));
@@ -24585,11 +24585,11 @@ function syncLegacyFromActive(agentDir) {
24585
24585
  return;
24586
24586
  const srcToken = slotTokenPath(agentDir, active);
24587
24587
  const srcMeta = slotMetaPath(agentDir, active);
24588
- if (!existsSync19(srcToken))
24588
+ if (!existsSync20(srcToken))
24589
24589
  return;
24590
24590
  mkdirSync14(claudeDir(agentDir), { recursive: true });
24591
24591
  atomicCopy(srcToken, legacyTokenPath(agentDir), 384);
24592
- if (existsSync19(srcMeta)) {
24592
+ if (existsSync20(srcMeta)) {
24593
24593
  atomicCopy(srcMeta, legacyMetaPath(agentDir), 384);
24594
24594
  }
24595
24595
  }
@@ -24613,7 +24613,7 @@ function migrateLegacyIfNeeded(agentDir) {
24613
24613
  return { migrated: false };
24614
24614
  }
24615
24615
  const legacyToken = legacyTokenPath(agentDir);
24616
- if (!existsSync19(legacyToken)) {
24616
+ if (!existsSync20(legacyToken)) {
24617
24617
  if (slots.length === 1 && slotExists(agentDir, slots[0])) {
24618
24618
  writeActiveSlot(agentDir, slots[0]);
24619
24619
  syncLegacyFromActive(agentDir);
@@ -24635,7 +24635,7 @@ function migrateLegacyIfNeeded(agentDir) {
24635
24635
  writeFileSync9(slotTokenPath(agentDir, slot), token + `
24636
24636
  `, { mode: 384 });
24637
24637
  const legacyMeta = legacyMetaPath(agentDir);
24638
- if (existsSync19(legacyMeta)) {
24638
+ if (existsSync20(legacyMeta)) {
24639
24639
  try {
24640
24640
  copyFileSync5(legacyMeta, slotMetaPath(agentDir, slot));
24641
24641
  } catch {
@@ -24698,16 +24698,16 @@ var init_accounts = __esm(() => {
24698
24698
  import { execFileSync as execFileSync11 } from "node:child_process";
24699
24699
  import {
24700
24700
  readFileSync as readFileSync19,
24701
- readdirSync as readdirSync10,
24702
- existsSync as existsSync20,
24701
+ readdirSync as readdirSync11,
24702
+ existsSync as existsSync21,
24703
24703
  writeFileSync as writeFileSync10,
24704
24704
  mkdirSync as mkdirSync15,
24705
24705
  mkdtempSync as mkdtempSync2,
24706
24706
  rmSync as rmSync5,
24707
24707
  chmodSync as chmodSync3,
24708
- statSync as statSync12
24708
+ statSync as statSync13
24709
24709
  } from "node:fs";
24710
- import { join as join14, resolve as resolve15 } from "node:path";
24710
+ import { join as join15, resolve as resolve15 } from "node:path";
24711
24711
  function extractCodeChallenge(url) {
24712
24712
  const match = url.match(/[?&]code_challenge=([A-Za-z0-9_-]+)/);
24713
24713
  return match ? match[1] : null;
@@ -24722,22 +24722,22 @@ function stripAnsi(text) {
24722
24722
  return text.replace(/\x1B\[[0-9;?]*[ -/]*[@-~]/g, "").replace(/\x1B[@-_]/g, "").replace(/\r/g, "");
24723
24723
  }
24724
24724
  function claudeDir2(agentDir) {
24725
- return join14(agentDir, ".claude");
24725
+ return join15(agentDir, ".claude");
24726
24726
  }
24727
24727
  function credentialsPath(agentDir) {
24728
- return join14(claudeDir2(agentDir), ".credentials.json");
24728
+ return join15(claudeDir2(agentDir), ".credentials.json");
24729
24729
  }
24730
24730
  function oauthTokenPath(agentDir) {
24731
- return join14(claudeDir2(agentDir), ".oauth-token");
24731
+ return join15(claudeDir2(agentDir), ".oauth-token");
24732
24732
  }
24733
24733
  function oauthTokenMetaPath(agentDir) {
24734
- return join14(claudeDir2(agentDir), ".oauth-token.meta.json");
24734
+ return join15(claudeDir2(agentDir), ".oauth-token.meta.json");
24735
24735
  }
24736
24736
  function authLogPath(agentDir) {
24737
- return join14(claudeDir2(agentDir), ".setup-token.log");
24737
+ return join15(claudeDir2(agentDir), ".setup-token.log");
24738
24738
  }
24739
24739
  function authSessionMetaPath(agentDir) {
24740
- return join14(claudeDir2(agentDir), ".setup-token.session.json");
24740
+ return join15(claudeDir2(agentDir), ".setup-token.session.json");
24741
24741
  }
24742
24742
  function authSessionName(name, slot) {
24743
24743
  const base = `switchroom-auth-${name.replace(/[^a-zA-Z0-9_.-]/g, "-")}`;
@@ -24765,7 +24765,7 @@ function captureTmuxPane(sessionName) {
24765
24765
  return tmux(["capture-pane", "-p", "-t", sessionName, "-S", "-200"]);
24766
24766
  }
24767
24767
  function readJsonFile(path) {
24768
- if (!existsSync20(path))
24768
+ if (!existsSync21(path))
24769
24769
  return null;
24770
24770
  try {
24771
24771
  return JSON.parse(readFileSync19(path, "utf-8"));
@@ -24775,7 +24775,7 @@ function readJsonFile(path) {
24775
24775
  }
24776
24776
  function readOAuthToken(agentDir) {
24777
24777
  const path = oauthTokenPath(agentDir);
24778
- if (!existsSync20(path))
24778
+ if (!existsSync21(path))
24779
24779
  return null;
24780
24780
  try {
24781
24781
  const token = readFileSync19(path, "utf-8").trim();
@@ -24787,7 +24787,7 @@ function readOAuthToken(agentDir) {
24787
24787
  function authFilesAreInaccessible(agentDir) {
24788
24788
  const probes = [credentialsPath(agentDir), oauthTokenPath(agentDir)];
24789
24789
  for (const p of probes) {
24790
- if (!existsSync20(p))
24790
+ if (!existsSync21(p))
24791
24791
  continue;
24792
24792
  try {
24793
24793
  readFileSync19(p, "utf-8");
@@ -24818,7 +24818,7 @@ function writeOAuthToken(agentDir, token, slot) {
24818
24818
  }
24819
24819
  function fileMtimeMs(filePath) {
24820
24820
  try {
24821
- return statSync12(filePath).mtimeMs;
24821
+ return statSync13(filePath).mtimeMs;
24822
24822
  } catch {
24823
24823
  return 0;
24824
24824
  }
@@ -24852,12 +24852,12 @@ function isSessionStale(agentDir, sessionName) {
24852
24852
  }
24853
24853
  function cleanupAuthTempDirs(agentDir) {
24854
24854
  const dir = claudeDir2(agentDir);
24855
- if (!existsSync20(dir))
24855
+ if (!existsSync21(dir))
24856
24856
  return;
24857
24857
  try {
24858
- for (const entry of readdirSync10(dir)) {
24858
+ for (const entry of readdirSync11(dir)) {
24859
24859
  if (entry.startsWith(".setup-token-tmp-")) {
24860
- rmSync5(join14(dir, entry), { recursive: true, force: true });
24860
+ rmSync5(join15(dir, entry), { recursive: true, force: true });
24861
24861
  }
24862
24862
  }
24863
24863
  } catch {}
@@ -24887,7 +24887,7 @@ function parseSetupTokenValue(output) {
24887
24887
  }
24888
24888
  function readTokenFromCredentialsFile(credentialsFilePath) {
24889
24889
  try {
24890
- if (!existsSync20(credentialsFilePath))
24890
+ if (!existsSync21(credentialsFilePath))
24891
24891
  return null;
24892
24892
  const raw = readFileSync19(credentialsFilePath, "utf-8");
24893
24893
  const parsed = JSON.parse(raw);
@@ -24910,7 +24910,7 @@ function hasPendingAuthSession(name, agentDir) {
24910
24910
  }
24911
24911
  function readCredentials(agentDir) {
24912
24912
  const credPath = credentialsPath(agentDir);
24913
- if (!existsSync20(credPath))
24913
+ if (!existsSync21(credPath))
24914
24914
  return null;
24915
24915
  try {
24916
24916
  const parsed = JSON.parse(readFileSync19(credPath, "utf-8"));
@@ -24922,9 +24922,9 @@ function readCredentials(agentDir) {
24922
24922
  function getAuthStatus(name, agentDir) {
24923
24923
  const pendingAuth = hasPendingAuthSession(name, agentDir);
24924
24924
  const creds = readCredentials(agentDir);
24925
- if (!existsSync20(oauthTokenPath(agentDir))) {
24925
+ if (!existsSync21(oauthTokenPath(agentDir))) {
24926
24926
  const activeSlot = readActiveSlot(agentDir);
24927
- if (activeSlot && existsSync20(slotTokenPath(agentDir, activeSlot))) {
24927
+ if (activeSlot && existsSync21(slotTokenPath(agentDir, activeSlot))) {
24928
24928
  try {
24929
24929
  syncLegacyFromActive(agentDir);
24930
24930
  } catch {}
@@ -25018,14 +25018,14 @@ function startAuthSession(name, agentDir, opts = {}) {
25018
25018
  rmSync5(logPath, { force: true });
25019
25019
  let configDir;
25020
25020
  if (opts.force) {
25021
- configDir = mkdtempSync2(join14(claudeDir2(agentDir), ".setup-token-tmp-"));
25021
+ configDir = mkdtempSync2(join15(claudeDir2(agentDir), ".setup-token-tmp-"));
25022
25022
  try {
25023
25023
  chmodSync3(configDir, 448);
25024
25024
  } catch {}
25025
25025
  } else {
25026
25026
  configDir = claudeDir2(agentDir);
25027
25027
  }
25028
- const credentialsMtimeAtStart = fileMtimeMs(join14(configDir, ".credentials.json"));
25028
+ const credentialsMtimeAtStart = fileMtimeMs(join15(configDir, ".credentials.json"));
25029
25029
  const commandParts = [];
25030
25030
  commandParts.push(`CLAUDE_CONFIG_DIR=${shellQuote(configDir)}`);
25031
25031
  commandParts.push(`LOG_PATH=${shellQuote(logPath)}`);
@@ -25066,7 +25066,7 @@ function startAuthSession(name, agentDir, opts = {}) {
25066
25066
  };
25067
25067
  }
25068
25068
  function readTokenFromLogFile(logPath) {
25069
- if (!existsSync20(logPath))
25069
+ if (!existsSync21(logPath))
25070
25070
  return null;
25071
25071
  try {
25072
25072
  const content = readFileSync19(logPath, "utf-8");
@@ -25113,7 +25113,7 @@ function submitAuthCode(name, agentDir, code, slot, _opts = {}) {
25113
25113
  tmux(["send-keys", "-l", "-t", sessionName, code.trim()]);
25114
25114
  tmux(["send-keys", "-t", sessionName, "Enter"]);
25115
25115
  const meta = readJsonFile(authSessionMetaPath(agentDir));
25116
- const credFileToWatch = meta?.configDir ? join14(meta.configDir, ".credentials.json") : credentialsPath(agentDir);
25116
+ const credFileToWatch = meta?.configDir ? join15(meta.configDir, ".credentials.json") : credentialsPath(agentDir);
25117
25117
  const credsMtimeSnapshot = meta?.credentialsMtimeAtStart ?? 0;
25118
25118
  const logPath = authLogPath(agentDir);
25119
25119
  let token = null;
@@ -25213,19 +25213,19 @@ var init_manager = __esm(() => {
25213
25213
 
25214
25214
  // src/agents/quarantine.ts
25215
25215
  import {
25216
- existsSync as existsSync25,
25216
+ existsSync as existsSync26,
25217
25217
  mkdirSync as mkdirSync16,
25218
25218
  readFileSync as readFileSync21,
25219
25219
  unlinkSync as unlinkSync6,
25220
25220
  writeFileSync as writeFileSync12
25221
25221
  } from "node:fs";
25222
- import { join as join16 } from "node:path";
25222
+ import { join as join17 } from "node:path";
25223
25223
  function quarantineMarkerPath(telegramStateDir) {
25224
- return join16(telegramStateDir, QUARANTINE_FILENAME);
25224
+ return join17(telegramStateDir, QUARANTINE_FILENAME);
25225
25225
  }
25226
25226
  function readQuarantineMarker(telegramStateDir) {
25227
25227
  const path = quarantineMarkerPath(telegramStateDir);
25228
- if (!existsSync25(path))
25228
+ if (!existsSync26(path))
25229
25229
  return null;
25230
25230
  try {
25231
25231
  const raw = readFileSync21(path, "utf-8");
@@ -25251,7 +25251,7 @@ function readQuarantineMarker(telegramStateDir) {
25251
25251
  }
25252
25252
  function clearQuarantineMarker(telegramStateDir) {
25253
25253
  const path = quarantineMarkerPath(telegramStateDir);
25254
- if (!existsSync25(path))
25254
+ if (!existsSync26(path))
25255
25255
  return false;
25256
25256
  try {
25257
25257
  unlinkSync6(path);
@@ -25261,7 +25261,7 @@ function clearQuarantineMarker(telegramStateDir) {
25261
25261
  }
25262
25262
  }
25263
25263
  function hostTelegramStateDir(agentsDir, name) {
25264
- return join16(agentsDir, name, "telegram");
25264
+ return join17(agentsDir, name, "telegram");
25265
25265
  }
25266
25266
  function readQuarantineMarkerForAgent(agentsDir, name) {
25267
25267
  return readQuarantineMarker(hostTelegramStateDir(agentsDir, name));
@@ -25807,10 +25807,10 @@ __export(exports_client2, {
25807
25807
  AuthBrokerClient: () => AuthBrokerClient
25808
25808
  });
25809
25809
  import * as net2 from "node:net";
25810
- import { existsSync as existsSync27 } from "node:fs";
25811
- import { homedir as homedir7 } from "node:os";
25810
+ import { existsSync as existsSync28 } from "node:fs";
25811
+ import { homedir as homedir8 } from "node:os";
25812
25812
  import { randomUUID } from "node:crypto";
25813
- import { join as join18 } from "node:path";
25813
+ import { join as join19 } from "node:path";
25814
25814
  function reviveDate(v) {
25815
25815
  if (v == null)
25816
25816
  return null;
@@ -25819,8 +25819,8 @@ function reviveDate(v) {
25819
25819
  const d = new Date(v);
25820
25820
  return Number.isNaN(d.getTime()) ? null : d;
25821
25821
  }
25822
- function operatorSocketPath(home2 = homedir7()) {
25823
- return join18(home2, ".switchroom", "state", "auth-broker-operator", "sock");
25822
+ function operatorSocketPath(home2 = homedir8()) {
25823
+ return join19(home2, ".switchroom", "state", "auth-broker-operator", "sock");
25824
25824
  }
25825
25825
  function resolveAuthBrokerSocketPath(opts) {
25826
25826
  if (opts?.socket)
@@ -26098,7 +26098,7 @@ async function withAuthBrokerClient(fn, opts) {
26098
26098
  }
26099
26099
  }
26100
26100
  function authBrokerSocketExists(opts) {
26101
- return existsSync27(resolveAuthBrokerSocketPath(opts));
26101
+ return existsSync28(resolveAuthBrokerSocketPath(opts));
26102
26102
  }
26103
26103
  var DEFAULT_TIMEOUT_MS2 = 5000, AuthBrokerError, AuthBrokerUnreachableError;
26104
26104
  var init_client2 = __esm(() => {
@@ -26157,44 +26157,44 @@ var init_broker_call = __esm(() => {
26157
26157
 
26158
26158
  // src/auth/account-store.ts
26159
26159
  import {
26160
- chownSync,
26161
- existsSync as existsSync28,
26160
+ chownSync as chownSync3,
26161
+ existsSync as existsSync29,
26162
26162
  mkdirSync as mkdirSync17,
26163
26163
  readFileSync as readFileSync23,
26164
- readdirSync as readdirSync14,
26164
+ readdirSync as readdirSync15,
26165
26165
  renameSync as renameSync7,
26166
26166
  rmSync as rmSync10,
26167
- statSync as statSync15,
26167
+ statSync as statSync16,
26168
26168
  writeFileSync as writeFileSync14
26169
26169
  } from "node:fs";
26170
- import { homedir as homedir9 } from "node:os";
26171
- import { join as join20, resolve as resolve22 } from "node:path";
26170
+ import { homedir as homedir10 } from "node:os";
26171
+ import { join as join21, resolve as resolve22 } from "node:path";
26172
26172
  function accountsRootOverride() {
26173
26173
  const v = process.env.SWITCHROOM_ACCOUNTS_DIR;
26174
26174
  if (v && v.length > 0 && v.startsWith("/"))
26175
26175
  return v;
26176
26176
  return;
26177
26177
  }
26178
- function accountsRoot(home2 = homedir9()) {
26178
+ function accountsRoot(home2 = homedir10()) {
26179
26179
  return accountsRootOverride() ?? resolve22(home2, ".switchroom", "accounts");
26180
26180
  }
26181
- function accountDir(label, home2 = homedir9()) {
26182
- return join20(accountsRoot(home2), label);
26181
+ function accountDir(label, home2 = homedir10()) {
26182
+ return join21(accountsRoot(home2), label);
26183
26183
  }
26184
- function accountCredentialsPath(label, home2 = homedir9()) {
26185
- return join20(accountDir(label, home2), "credentials.json");
26184
+ function accountCredentialsPath(label, home2 = homedir10()) {
26185
+ return join21(accountDir(label, home2), "credentials.json");
26186
26186
  }
26187
- function accountMetaPath(label, home2 = homedir9()) {
26188
- return join20(accountDir(label, home2), "meta.json");
26187
+ function accountMetaPath(label, home2 = homedir10()) {
26188
+ return join21(accountDir(label, home2), "meta.json");
26189
26189
  }
26190
- function listAccounts(home2 = homedir9()) {
26190
+ function listAccounts(home2 = homedir10()) {
26191
26191
  const root = accountsRoot(home2);
26192
- if (!existsSync28(root))
26192
+ if (!existsSync29(root))
26193
26193
  return [];
26194
26194
  try {
26195
- return readdirSync14(root).filter((name) => {
26195
+ return readdirSync15(root).filter((name) => {
26196
26196
  try {
26197
- return statSync15(join20(root, name)).isDirectory();
26197
+ return statSync16(join21(root, name)).isDirectory();
26198
26198
  } catch {
26199
26199
  return false;
26200
26200
  }
@@ -26203,9 +26203,9 @@ function listAccounts(home2 = homedir9()) {
26203
26203
  return [];
26204
26204
  }
26205
26205
  }
26206
- function readAccountCredentials(label, home2 = homedir9()) {
26206
+ function readAccountCredentials(label, home2 = homedir10()) {
26207
26207
  const p = accountCredentialsPath(label, home2);
26208
- if (!existsSync28(p))
26208
+ if (!existsSync29(p))
26209
26209
  return null;
26210
26210
  try {
26211
26211
  return JSON.parse(readFileSync23(p, "utf-8"));
@@ -26213,9 +26213,9 @@ function readAccountCredentials(label, home2 = homedir9()) {
26213
26213
  return null;
26214
26214
  }
26215
26215
  }
26216
- function readAccountMeta(label, home2 = homedir9()) {
26216
+ function readAccountMeta(label, home2 = homedir10()) {
26217
26217
  const p = accountMetaPath(label, home2);
26218
- if (!existsSync28(p))
26218
+ if (!existsSync29(p))
26219
26219
  return null;
26220
26220
  try {
26221
26221
  return JSON.parse(readFileSync23(p, "utf-8"));
@@ -26223,7 +26223,7 @@ function readAccountMeta(label, home2 = homedir9()) {
26223
26223
  return null;
26224
26224
  }
26225
26225
  }
26226
- function accountHealth(label, now = Date.now(), home2 = homedir9()) {
26226
+ function accountHealth(label, now = Date.now(), home2 = homedir10()) {
26227
26227
  const creds = readAccountCredentials(label, home2);
26228
26228
  if (!creds?.claudeAiOauth?.accessToken)
26229
26229
  return "missing-credentials";
@@ -26239,7 +26239,7 @@ function accountHealth(label, now = Date.now(), home2 = homedir9()) {
26239
26239
  }
26240
26240
  return "healthy";
26241
26241
  }
26242
- function getAccountInfos(now = Date.now(), home2 = homedir9()) {
26242
+ function getAccountInfos(now = Date.now(), home2 = homedir10()) {
26243
26243
  return listAccounts(home2).map((label) => {
26244
26244
  const creds = readAccountCredentials(label, home2);
26245
26245
  const meta = readAccountMeta(label, home2);
@@ -26908,15 +26908,15 @@ var init_disconnect = __esm(() => {
26908
26908
  });
26909
26909
 
26910
26910
  // src/vault/approvals/client.ts
26911
- import { existsSync as existsSync29 } from "node:fs";
26912
- import { homedir as homedir10 } from "node:os";
26913
- import { join as join21 } from "node:path";
26914
- function kernelOperatorSocketPath(home2 = homedir10()) {
26915
- return join21(home2, ".switchroom", "state", "kernel-operator", "sock");
26911
+ import { existsSync as existsSync30 } from "node:fs";
26912
+ import { homedir as homedir11 } from "node:os";
26913
+ import { join as join22 } from "node:path";
26914
+ function kernelOperatorSocketPath(home2 = homedir11()) {
26915
+ return join22(home2, ".switchroom", "state", "kernel-operator", "sock");
26916
26916
  }
26917
- function resolveKernelOperatorSocket(home2 = homedir10()) {
26917
+ function resolveKernelOperatorSocket(home2 = homedir11()) {
26918
26918
  const p = kernelOperatorSocketPath(home2);
26919
- return existsSync29(p) ? p : null;
26919
+ return existsSync30(p) ? p : null;
26920
26920
  }
26921
26921
  function resolveKernelSocketPath(opts) {
26922
26922
  if (opts?.socket)
@@ -27995,8 +27995,8 @@ __export(exports_via_claude, {
27995
27995
  POST_PASTE_RULES: () => POST_PASTE_RULES
27996
27996
  });
27997
27997
  import { execFileSync as execFileSync14, spawnSync as spawnSync2 } from "node:child_process";
27998
- import { existsSync as existsSync30, mkdirSync as mkdirSync18, readFileSync as readFileSync26 } from "node:fs";
27999
- import { join as join22, resolve as resolve23 } from "node:path";
27998
+ import { existsSync as existsSync31, mkdirSync as mkdirSync18, readFileSync as readFileSync26 } from "node:fs";
27999
+ import { join as join23, resolve as resolve23 } from "node:path";
28000
28000
  function tmuxHasSession(session) {
28001
28001
  const r = spawnSync2("tmux", ["has-session", "-t", session], {
28002
28002
  stdio: ["ignore", "ignore", "ignore"]
@@ -28042,7 +28042,7 @@ async function runViaClaude(opts) {
28042
28042
  const poll = opts.pollMs ?? VIA_CLAUDE_DEFAULTS.pollMs;
28043
28043
  const configDir = resolve23(opts.configDir);
28044
28044
  mkdirSync18(configDir, { recursive: true });
28045
- const credentialsPath2 = join22(configDir, ".credentials.json");
28045
+ const credentialsPath2 = join23(configDir, ".credentials.json");
28046
28046
  const capture = opts.capturePane ?? (() => tmuxCapturePane(SESSION));
28047
28047
  const send = opts.sendKeys ?? ((keys, literal) => tmuxSendKeys(SESSION, keys, literal === true));
28048
28048
  if (!opts.spawnClaude) {
@@ -28103,7 +28103,7 @@ async function runViaClaude(opts) {
28103
28103
  log(" Waiting for credentials to land\u2026");
28104
28104
  while (Date.now() < phase2Deadline) {
28105
28105
  await sleep3(poll);
28106
- if (existsSync30(credentialsPath2)) {
28106
+ if (existsSync31(credentialsPath2)) {
28107
28107
  await sleep3(200);
28108
28108
  const raw = readFileSync26(credentialsPath2, "utf-8");
28109
28109
  let parsed;
@@ -28684,10 +28684,10 @@ var init_protocol3 = __esm(() => {
28684
28684
  });
28685
28685
 
28686
28686
  // src/host-control/audit-reader.ts
28687
- import { homedir as homedir19 } from "node:os";
28688
- import { join as join37 } from "node:path";
28689
- function defaultAuditLogPath2(home2 = homedir19()) {
28690
- return join37(home2, ".switchroom", "host-control-audit.log");
28687
+ import { homedir as homedir20 } from "node:os";
28688
+ import { join as join38 } from "node:path";
28689
+ function defaultAuditLogPath2(home2 = homedir20()) {
28690
+ return join38(home2, ".switchroom", "host-control-audit.log");
28691
28691
  }
28692
28692
  function parseAuditLine2(line) {
28693
28693
  const trimmed = line.trim();
@@ -28946,19 +28946,19 @@ var init_thinking_effort_risk = __esm(() => {
28946
28946
 
28947
28947
  // src/manifest.ts
28948
28948
  import {
28949
- existsSync as existsSync50,
28949
+ existsSync as existsSync51,
28950
28950
  readFileSync as readFileSync46,
28951
- readdirSync as readdirSync18
28951
+ readdirSync as readdirSync19
28952
28952
  } from "node:fs";
28953
- import { dirname as dirname11, join as join44 } from "node:path";
28953
+ import { dirname as dirname12, join as join45 } from "node:path";
28954
28954
  import { execSync as execSync2 } from "node:child_process";
28955
28955
  function locateManifestPath() {
28956
28956
  let dir = import.meta.dirname;
28957
28957
  for (let i = 0;i < 10 && dir && dir !== "/"; i++) {
28958
- const candidate = join44(dir, "dependencies.json");
28959
- if (existsSync50(candidate))
28958
+ const candidate = join45(dir, "dependencies.json");
28959
+ if (existsSync51(candidate))
28960
28960
  return candidate;
28961
- dir = dirname11(dir);
28961
+ dir = dirname12(dir);
28962
28962
  }
28963
28963
  return null;
28964
28964
  }
@@ -29025,14 +29025,14 @@ function probeClaudeVersion() {
29025
29025
  }
29026
29026
  function probePlaywrightMcpVersion() {
29027
29027
  const home2 = process.env.HOME ?? "";
29028
- const npxCache = join44(home2, ".npm/_npx");
29029
- if (!existsSync50(npxCache))
29028
+ const npxCache = join45(home2, ".npm/_npx");
29029
+ if (!existsSync51(npxCache))
29030
29030
  return null;
29031
29031
  try {
29032
- const entries = readdirSync18(npxCache);
29032
+ const entries = readdirSync19(npxCache);
29033
29033
  for (const entry of entries) {
29034
- const pkgPath = join44(npxCache, entry, "node_modules/@playwright/mcp/package.json");
29035
- if (existsSync50(pkgPath)) {
29034
+ const pkgPath = join45(npxCache, entry, "node_modules/@playwright/mcp/package.json");
29035
+ if (existsSync51(pkgPath)) {
29036
29036
  try {
29037
29037
  const pkg = JSON.parse(readFileSync46(pkgPath, "utf-8"));
29038
29038
  if (pkg.version)
@@ -29473,11 +29473,11 @@ var init_doctor_docker = __esm(() => {
29473
29473
  });
29474
29474
 
29475
29475
  // src/cli/doctor-auth-broker.ts
29476
- import { existsSync as existsSync51, readFileSync as readFileSync48 } from "node:fs";
29476
+ import { existsSync as existsSync52, readFileSync as readFileSync48 } from "node:fs";
29477
29477
  import { createHash as createHash10 } from "node:crypto";
29478
29478
  import { spawnSync as spawnSync6 } from "node:child_process";
29479
- import { homedir as homedir24 } from "node:os";
29480
- import { join as join45 } from "node:path";
29479
+ import { homedir as homedir25 } from "node:os";
29480
+ import { join as join46 } from "node:path";
29481
29481
  function defaultDockerInspect(container, format) {
29482
29482
  try {
29483
29483
  const r = spawnSync6("docker", ["inspect", "-f", format, container], { encoding: "utf-8", timeout: 5000 });
@@ -29577,8 +29577,8 @@ function checkAuthBrokerPerAgentSockets(config, deps = {}) {
29577
29577
  }
29578
29578
  function checkAuthBrokerDrift(deps = {}) {
29579
29579
  const stateDir = resolveStateDir(deps);
29580
- const indexPath = join45(stateDir, "sha-index.json");
29581
- if (!existsSync51(indexPath)) {
29580
+ const indexPath = join46(stateDir, "sha-index.json");
29581
+ if (!existsSync52(indexPath)) {
29582
29582
  return {
29583
29583
  name: "auth-broker: drift",
29584
29584
  status: "ok",
@@ -29596,12 +29596,12 @@ function checkAuthBrokerDrift(deps = {}) {
29596
29596
  fix: "Inspect `~/.switchroom/state/auth-broker/sha-index.json` for corruption."
29597
29597
  };
29598
29598
  }
29599
- const home2 = deps.home ?? homedir24();
29599
+ const home2 = deps.home ?? homedir25();
29600
29600
  const divergent = [];
29601
29601
  const missingOnDisk = [];
29602
29602
  for (const [label, expected] of Object.entries(index)) {
29603
29603
  const credsPath = accountCredentialsPath(label, home2);
29604
- if (!existsSync51(credsPath)) {
29604
+ if (!existsSync52(credsPath)) {
29605
29605
  missingOnDisk.push(label);
29606
29606
  continue;
29607
29607
  }
@@ -29638,8 +29638,8 @@ function checkAuthBrokerDrift(deps = {}) {
29638
29638
  }
29639
29639
  function checkAuthBrokerThresholdViolations(deps = {}) {
29640
29640
  const stateDir = resolveStateDir(deps);
29641
- const path4 = join45(stateDir, "threshold-violations.json");
29642
- if (!existsSync51(path4)) {
29641
+ const path4 = join46(stateDir, "threshold-violations.json");
29642
+ if (!existsSync52(path4)) {
29643
29643
  return {
29644
29644
  name: "auth-broker: threshold violations",
29645
29645
  status: "ok",
@@ -29682,9 +29682,9 @@ function checkAuthBrokerActiveAccount(config, deps = {}) {
29682
29682
  fix: "Run `switchroom auth use <label>` to pin a fleet-wide account, then `switchroom apply`. Without an active account every agent boot fails."
29683
29683
  };
29684
29684
  }
29685
- const home2 = deps.home ?? homedir24();
29685
+ const home2 = deps.home ?? homedir25();
29686
29686
  const dir = accountDir(active, home2);
29687
- if (!existsSync51(dir)) {
29687
+ if (!existsSync52(dir)) {
29688
29688
  return {
29689
29689
  name: "auth-broker: fleet active account",
29690
29690
  status: "fail",
@@ -29693,7 +29693,7 @@ function checkAuthBrokerActiveAccount(config, deps = {}) {
29693
29693
  };
29694
29694
  }
29695
29695
  const creds = accountCredentialsPath(active, home2);
29696
- if (!existsSync51(creds)) {
29696
+ if (!existsSync52(creds)) {
29697
29697
  return {
29698
29698
  name: "auth-broker: fleet active account",
29699
29699
  status: "fail",
@@ -29830,27 +29830,27 @@ var init_doctor_hostd = () => {};
29830
29830
  import {
29831
29831
  accessSync,
29832
29832
  constants as fsConstants4,
29833
- existsSync as existsSync52,
29834
- realpathSync as realpathSync4,
29835
- statSync as statSync22
29833
+ existsSync as existsSync53,
29834
+ realpathSync as realpathSync5,
29835
+ statSync as statSync23
29836
29836
  } from "node:fs";
29837
- import { userInfo, homedir as homedir25 } from "node:os";
29838
- import { join as join46 } from "node:path";
29837
+ import { userInfo, homedir as homedir26 } from "node:os";
29838
+ import { join as join47 } from "node:path";
29839
29839
  function resolveVaultPath2(config) {
29840
29840
  return config.vault?.path ? config.vault.path.replace(/^~/, process.env.HOME ?? "") : resolveStatePath("vault.enc");
29841
29841
  }
29842
29842
  function defaultStatVault(path4) {
29843
- if (!existsSync52(path4)) {
29843
+ if (!existsSync53(path4)) {
29844
29844
  return { exists: false, readable: false, uid: -1, mode: 0, realPath: path4 };
29845
29845
  }
29846
29846
  let real = path4;
29847
29847
  try {
29848
- real = realpathSync4(path4);
29848
+ real = realpathSync5(path4);
29849
29849
  } catch {}
29850
29850
  let uid = -1;
29851
29851
  let mode = 0;
29852
29852
  try {
29853
- const s = statSync22(real);
29853
+ const s = statSync23(real);
29854
29854
  uid = s.uid;
29855
29855
  mode = s.mode & 511;
29856
29856
  } catch {
@@ -29973,7 +29973,7 @@ async function runSecretAccessChecks(config, deps = {}) {
29973
29973
  };
29974
29974
  const passphrase = deps.passphrase ?? process.env.SWITCHROOM_VAULT_PASSPHRASE;
29975
29975
  if (!passphrase) {
29976
- const sock = deps.brokerOperatorSocket ?? join46(homedir25(), ".switchroom", "broker-operator", "sock");
29976
+ const sock = deps.brokerOperatorSocket ?? join47(homedir26(), ".switchroom", "broker-operator", "sock");
29977
29977
  const preflight = deps.preflight ?? ((a, k) => defaultPreflight(sock, a, k));
29978
29978
  for (const name of Object.keys(config.agents ?? {})) {
29979
29979
  const resolved = resolveAgentConfig(config.defaults, config.profiles, config.agents[name]);
@@ -30058,8 +30058,8 @@ import {
30058
30058
  existsSync as realExistsSync,
30059
30059
  readFileSync as realReadFileSync
30060
30060
  } from "node:fs";
30061
- import { join as join47, resolve as resolve30 } from "node:path";
30062
- import { homedir as homedir26 } from "node:os";
30061
+ import { join as join48, resolve as resolve30 } from "node:path";
30062
+ import { homedir as homedir27 } from "node:os";
30063
30063
  function resolveDeps(config, deps) {
30064
30064
  let agentsDir = deps.agentsDir;
30065
30065
  if (agentsDir === undefined) {
@@ -30182,8 +30182,8 @@ function checkScaffoldWiring(config, driveAgents, d) {
30182
30182
  });
30183
30183
  continue;
30184
30184
  }
30185
- const mcpPath = join47(agentDir, ".mcp.json");
30186
- const claudeJsonPath = join47(agentDir, ".claude", ".claude.json");
30185
+ const mcpPath = join48(agentDir, ".mcp.json");
30186
+ const claudeJsonPath = join48(agentDir, ".claude", ".claude.json");
30187
30187
  const mcpRead = readJson(d, mcpPath);
30188
30188
  const trustRead = readJson(d, claudeJsonPath);
30189
30189
  if (mcpRead.kind === "unreadable" || trustRead.kind === "unreadable") {
@@ -30296,7 +30296,7 @@ async function runDriveBrokerReachabilityChecks(config, deps = {}) {
30296
30296
  }
30297
30297
  ];
30298
30298
  }
30299
- const sock = deps.brokerOperatorSocket ?? join47(homedir26(), ".switchroom", "broker-operator", "sock");
30299
+ const sock = deps.brokerOperatorSocket ?? join48(homedir27(), ".switchroom", "broker-operator", "sock");
30300
30300
  const preflight = deps.preflight ?? ((a, k) => defaultPreflight(sock, a, k));
30301
30301
  const results = [];
30302
30302
  for (const agent of driveAgents) {
@@ -30350,8 +30350,8 @@ import {
30350
30350
  readSync as realReadSync,
30351
30351
  closeSync as realCloseSync
30352
30352
  } from "node:fs";
30353
- import { join as join48 } from "node:path";
30354
- import { homedir as homedir27 } from "node:os";
30353
+ import { join as join49 } from "node:path";
30354
+ import { homedir as homedir28 } from "node:os";
30355
30355
  function defaultReadHead(p, n) {
30356
30356
  let fd;
30357
30357
  try {
@@ -30379,7 +30379,7 @@ function resolveDeps2(config, deps) {
30379
30379
  }
30380
30380
  }
30381
30381
  return {
30382
- homeDir: deps.homeDir ?? homedir27(),
30382
+ homeDir: deps.homeDir ?? homedir28(),
30383
30383
  agentsDir,
30384
30384
  existsSync: deps.existsSync ?? ((p) => realExistsSync2(p)),
30385
30385
  readFileSync: deps.readFileSync ?? ((p) => realReadFileSync2(p, "utf-8")),
@@ -30408,7 +30408,7 @@ function runWebkiteChecks(config, deps = {}) {
30408
30408
  return [];
30409
30409
  const d = resolveDeps2(config, deps);
30410
30410
  const results = [];
30411
- const binPath = join48(d.homeDir, ".switchroom", "bin", "webkite");
30411
+ const binPath = join49(d.homeDir, ".switchroom", "bin", "webkite");
30412
30412
  if (!d.existsSync(binPath)) {
30413
30413
  results.push({
30414
30414
  name: "webkite: binary",
@@ -30438,12 +30438,12 @@ function runWebkiteChecks(config, deps = {}) {
30438
30438
  });
30439
30439
  }
30440
30440
  }
30441
- const cloakDir = join48(d.homeDir, ".cloakbrowser");
30441
+ const cloakDir = join49(d.homeDir, ".cloakbrowser");
30442
30442
  let chromeFound = false;
30443
30443
  if (d.existsSync(cloakDir)) {
30444
30444
  try {
30445
30445
  for (const entry of d.readdirSync(cloakDir)) {
30446
- if (entry.startsWith("chromium-") && d.existsSync(join48(cloakDir, entry, "chrome"))) {
30446
+ if (entry.startsWith("chromium-") && d.existsSync(join49(cloakDir, entry, "chrome"))) {
30447
30447
  chromeFound = true;
30448
30448
  break;
30449
30449
  }
@@ -30469,9 +30469,9 @@ function runWebkiteChecks(config, deps = {}) {
30469
30469
  return results;
30470
30470
  }
30471
30471
  for (const agent of enabledAgents) {
30472
- const agentDir = join48(d.agentsDir, agent);
30473
- const settingsPath = join48(agentDir, ".claude", "settings.json");
30474
- const mcpPath = join48(agentDir, ".mcp.json");
30472
+ const agentDir = join49(d.agentsDir, agent);
30473
+ const settingsPath = join49(agentDir, ".claude", "settings.json");
30474
+ const mcpPath = join49(agentDir, ".mcp.json");
30475
30475
  if (!d.existsSync(settingsPath) && !d.existsSync(mcpPath)) {
30476
30476
  continue;
30477
30477
  }
@@ -30535,7 +30535,7 @@ var init_doctor_webkite = __esm(() => {
30535
30535
  });
30536
30536
 
30537
30537
  // src/cli/doctor-scaffold-wiring.ts
30538
- import { join as join49, resolve as resolve31 } from "node:path";
30538
+ import { join as join50, resolve as resolve31 } from "node:path";
30539
30539
  function readJson2(d, path4) {
30540
30540
  if (!d.existsSync(path4))
30541
30541
  return { kind: "absent" };
@@ -30578,8 +30578,8 @@ function checkIntegrationScaffoldWiring(args) {
30578
30578
  });
30579
30579
  continue;
30580
30580
  }
30581
- const mcpPath = join49(agentDir, ".mcp.json");
30582
- const claudeJsonPath = join49(agentDir, ".claude", ".claude.json");
30581
+ const mcpPath = join50(agentDir, ".mcp.json");
30582
+ const claudeJsonPath = join50(agentDir, ".claude", ".claude.json");
30583
30583
  const mcpRead = readJson2(deps, mcpPath);
30584
30584
  const trustRead = readJson2(deps, claudeJsonPath);
30585
30585
  if (mcpRead.kind === "unreadable" || trustRead.kind === "unreadable") {
@@ -30643,14 +30643,14 @@ import {
30643
30643
  existsSync as realExistsSync3,
30644
30644
  readFileSync as realReadFileSync3
30645
30645
  } from "node:fs";
30646
- import { join as join50 } from "node:path";
30647
- import { homedir as homedir28 } from "node:os";
30646
+ import { join as join51 } from "node:path";
30647
+ import { homedir as homedir29 } from "node:os";
30648
30648
  function resolveDeps3(deps) {
30649
- const home2 = deps.homeDir?.() ?? homedir28();
30649
+ const home2 = deps.homeDir?.() ?? homedir29();
30650
30650
  return {
30651
30651
  existsSync: deps.existsSync ?? realExistsSync3,
30652
30652
  readFileSync: deps.readFileSync ?? realReadFileSync3,
30653
- agentsDir: join50(home2, ".switchroom", "agents"),
30653
+ agentsDir: join51(home2, ".switchroom", "agents"),
30654
30654
  now: deps.now ?? Date.now
30655
30655
  };
30656
30656
  }
@@ -30733,7 +30733,7 @@ function checkOAuthClient2(config, anyAgentEnabled) {
30733
30733
  ];
30734
30734
  }
30735
30735
  function readHeartbeat(d, agentName) {
30736
- const path4 = join50(d.agentsDir, agentName, "m365-launcher.heartbeat.json");
30736
+ const path4 = join51(d.agentsDir, agentName, "m365-launcher.heartbeat.json");
30737
30737
  if (!d.existsSync(path4)) {
30738
30738
  return { error: "heartbeat file missing \u2014 launcher has not yet started" };
30739
30739
  }
@@ -30830,15 +30830,15 @@ import {
30830
30830
  readFileSync as realReadFileSync4,
30831
30831
  statSync as realStatSync
30832
30832
  } from "node:fs";
30833
- import { join as join51 } from "node:path";
30834
- import { homedir as homedir29 } from "node:os";
30833
+ import { join as join52 } from "node:path";
30834
+ import { homedir as homedir30 } from "node:os";
30835
30835
  function resolveDeps4(deps) {
30836
- const home2 = deps.homeDir?.() ?? homedir29();
30836
+ const home2 = deps.homeDir?.() ?? homedir30();
30837
30837
  return {
30838
30838
  existsSync: deps.existsSync ?? realExistsSync4,
30839
30839
  readFileSync: deps.readFileSync ?? realReadFileSync4,
30840
30840
  statSync: deps.statSync ?? realStatSync,
30841
- agentsDir: join51(home2, ".switchroom", "agents"),
30841
+ agentsDir: join52(home2, ".switchroom", "agents"),
30842
30842
  now: deps.now ?? Date.now,
30843
30843
  vaultAclReader: deps.vaultAclReader ?? (async () => ({ kind: "unreachable", msg: "no default reader wired" }))
30844
30844
  };
@@ -30963,7 +30963,7 @@ function checkLauncherHeartbeat2(notionAgents, d) {
30963
30963
  return [];
30964
30964
  const results = [];
30965
30965
  for (const name of notionAgents) {
30966
- const heartbeatPath = join51(d.agentsDir, name, "notion-launcher.heartbeat.json");
30966
+ const heartbeatPath = join52(d.agentsDir, name, "notion-launcher.heartbeat.json");
30967
30967
  if (!d.existsSync(heartbeatPath)) {
30968
30968
  results.push({
30969
30969
  name: `notion:launcher-heartbeat:${name}`,
@@ -31038,12 +31038,12 @@ import {
31038
31038
  readdirSync as realReaddirSync2,
31039
31039
  statSync as realStatSync2
31040
31040
  } from "node:fs";
31041
- import { homedir as homedir30 } from "node:os";
31042
- import { join as join52 } from "node:path";
31041
+ import { homedir as homedir31 } from "node:os";
31042
+ import { join as join53 } from "node:path";
31043
31043
  function runCredentialsMigrationChecks(config, deps = {}) {
31044
- const credDir = deps.credentialsDir ?? join52(homedir30(), ".switchroom", "credentials");
31045
- const existsSync53 = deps.existsSync ?? ((p) => realExistsSync5(p));
31046
- const readdirSync20 = deps.readdirSync ?? ((p) => realReaddirSync2(p));
31044
+ const credDir = deps.credentialsDir ?? join53(homedir31(), ".switchroom", "credentials");
31045
+ const existsSync54 = deps.existsSync ?? ((p) => realExistsSync5(p));
31046
+ const readdirSync21 = deps.readdirSync ?? ((p) => realReaddirSync2(p));
31047
31047
  const isDirectory = deps.isDirectory ?? ((p) => {
31048
31048
  try {
31049
31049
  return realStatSync2(p).isDirectory();
@@ -31051,12 +31051,12 @@ function runCredentialsMigrationChecks(config, deps = {}) {
31051
31051
  return false;
31052
31052
  }
31053
31053
  });
31054
- if (!existsSync53(credDir))
31054
+ if (!existsSync54(credDir))
31055
31055
  return [];
31056
31056
  const agentNames = new Set(Object.keys(config.agents ?? {}));
31057
31057
  let entries;
31058
31058
  try {
31059
- entries = readdirSync20(credDir);
31059
+ entries = readdirSync21(credDir);
31060
31060
  } catch {
31061
31061
  return [
31062
31062
  {
@@ -31069,7 +31069,7 @@ function runCredentialsMigrationChecks(config, deps = {}) {
31069
31069
  const flat = [];
31070
31070
  const perAgentDirs = [];
31071
31071
  for (const e of entries) {
31072
- const full = join52(credDir, e);
31072
+ const full = join53(credDir, e);
31073
31073
  if (isDirectory(full) && agentNames.has(e)) {
31074
31074
  perAgentDirs.push(e);
31075
31075
  } else {
@@ -31192,19 +31192,19 @@ var init_doctor_inlined_secrets = __esm(() => {
31192
31192
 
31193
31193
  // src/cli/doctor-audit-integrity.ts
31194
31194
  import { readFileSync as fsReadFileSync2 } from "node:fs";
31195
- import { homedir as homedir31 } from "node:os";
31196
- import { join as join53 } from "node:path";
31195
+ import { homedir as homedir32 } from "node:os";
31196
+ import { join as join54 } from "node:path";
31197
31197
  function rootWrittenLogs(home2) {
31198
31198
  return [
31199
- { label: "vault-broker", path: join53(home2, ".switchroom", "vault-audit.log") },
31199
+ { label: "vault-broker", path: join54(home2, ".switchroom", "vault-audit.log") },
31200
31200
  {
31201
31201
  label: "hostd",
31202
- path: join53(home2, ".switchroom", "host-control-audit.log")
31202
+ path: join54(home2, ".switchroom", "host-control-audit.log")
31203
31203
  }
31204
31204
  ];
31205
31205
  }
31206
31206
  function runAuditIntegrityChecks(deps = {}) {
31207
- const home2 = deps.homeDir ?? homedir31();
31207
+ const home2 = deps.homeDir ?? homedir32();
31208
31208
  const read = deps.readFileSync ?? ((p) => fsReadFileSync2(p, "utf8"));
31209
31209
  const results = [];
31210
31210
  for (const { label, path: path4 } of rootWrittenLogs(home2)) {
@@ -31261,16 +31261,16 @@ var init_doctor_audit_integrity = __esm(() => {
31261
31261
  });
31262
31262
 
31263
31263
  // src/cli/doctor-agent-smoke.ts
31264
- import { existsSync as existsSync53 } from "node:fs";
31265
- import { homedir as homedir32 } from "node:os";
31266
- import { join as join54 } from "node:path";
31264
+ import { existsSync as existsSync54 } from "node:fs";
31265
+ import { homedir as homedir33 } from "node:os";
31266
+ import { join as join55 } from "node:path";
31267
31267
  import { randomUUID as randomUUID5 } from "node:crypto";
31268
31268
  async function runAgentSmokeChecks(config, deps = {}) {
31269
31269
  if (deps.fast)
31270
31270
  return [];
31271
- const home2 = deps.homeDir ?? homedir32();
31272
- const sock = deps.operatorSockPath ?? join54(home2, ".switchroom", "hostd", "operator", "sock");
31273
- if (!deps.hostdRequestImpl && !existsSync53(sock)) {
31271
+ const home2 = deps.homeDir ?? homedir33();
31272
+ const sock = deps.operatorSockPath ?? join55(home2, ".switchroom", "hostd", "operator", "sock");
31273
+ if (!deps.hostdRequestImpl && !existsSync54(sock)) {
31274
31274
  return [
31275
31275
  {
31276
31276
  name: "agent liveness",
@@ -31348,9 +31348,9 @@ var init_doctor_agent_smoke = __esm(() => {
31348
31348
 
31349
31349
  // src/cli/doctor-vault-broker-durability.ts
31350
31350
  import { execFileSync as execFileSync18 } from "node:child_process";
31351
- import { existsSync as existsSync54, statSync as statSync23 } from "node:fs";
31352
- import { homedir as homedir33 } from "node:os";
31353
- import { join as join55 } from "node:path";
31351
+ import { existsSync as existsSync55, statSync as statSync24 } from "node:fs";
31352
+ import { homedir as homedir34 } from "node:os";
31353
+ import { join as join56 } from "node:path";
31354
31354
  function probeBindMountInode(hostPath, brokerContainerPath, opts) {
31355
31355
  const statHost = opts?.statHost ?? defaultStatHost;
31356
31356
  const statBroker = opts?.statBroker ?? defaultStatBroker;
@@ -31372,10 +31372,10 @@ function probeBindMountInode(hostPath, brokerContainerPath, opts) {
31372
31372
  };
31373
31373
  }
31374
31374
  function defaultStatHost(p) {
31375
- if (!existsSync54(p))
31375
+ if (!existsSync55(p))
31376
31376
  return null;
31377
31377
  try {
31378
- const s = statSync23(p, { bigint: true });
31378
+ const s = statSync24(p, { bigint: true });
31379
31379
  return { ino: s.ino, size: Number(s.size) };
31380
31380
  } catch {
31381
31381
  return null;
@@ -31493,22 +31493,22 @@ function defaultBrokerStatusProbe() {
31493
31493
  }
31494
31494
  }
31495
31495
  function runVaultBrokerDurabilityChecks(_config, opts) {
31496
- const home2 = homedir33();
31496
+ const home2 = homedir34();
31497
31497
  const probe2 = opts?.inodeProbe ?? probeBindMountInode;
31498
31498
  return [
31499
31499
  probeBrokerUnlocked(opts?.statusProbe),
31500
31500
  probeAutoUnlockBlob(home2),
31501
31501
  probeMachineIdMount(),
31502
- formatBindMountResult("vault-broker: vault.enc bind mount", join55(home2, ".switchroom", "vault", "vault.enc"), "/state/vault/vault.enc", probe2(join55(home2, ".switchroom", "vault", "vault.enc"), "/state/vault/vault.enc")),
31503
- formatBindMountResult("vault-broker: vault-grants.db bind mount (#1737)", join55(home2, ".switchroom", "vault-grants.db"), "/root/.switchroom/vault-grants.db", probe2(join55(home2, ".switchroom", "vault-grants.db"), "/root/.switchroom/vault-grants.db")),
31504
- formatBindMountResult("vault-broker: vault-audit.log bind mount (#1025)", join55(home2, ".switchroom", "vault-audit.log"), "/root/.switchroom/vault-audit.log", probe2(join55(home2, ".switchroom", "vault-audit.log"), "/root/.switchroom/vault-audit.log")),
31502
+ formatBindMountResult("vault-broker: vault.enc bind mount", join56(home2, ".switchroom", "vault", "vault.enc"), "/state/vault/vault.enc", probe2(join56(home2, ".switchroom", "vault", "vault.enc"), "/state/vault/vault.enc")),
31503
+ formatBindMountResult("vault-broker: vault-grants.db bind mount (#1737)", join56(home2, ".switchroom", "vault-grants.db"), "/root/.switchroom/vault-grants.db", probe2(join56(home2, ".switchroom", "vault-grants.db"), "/root/.switchroom/vault-grants.db")),
31504
+ formatBindMountResult("vault-broker: vault-audit.log bind mount (#1025)", join56(home2, ".switchroom", "vault-audit.log"), "/root/.switchroom/vault-audit.log", probe2(join56(home2, ".switchroom", "vault-audit.log"), "/root/.switchroom/vault-audit.log")),
31505
31505
  probeKernelDbDurability(home2, {
31506
31506
  statBroker: opts?.kernelStatBroker
31507
31507
  })
31508
31508
  ];
31509
31509
  }
31510
31510
  function probeKernelDbDurability(home2, opts) {
31511
- const hostDir = join55(home2, ".switchroom", "approvals");
31511
+ const hostDir = join56(home2, ".switchroom", "approvals");
31512
31512
  const containerDir = "/state/approvals";
31513
31513
  const name = "approval-kernel: approvals bind mount (allow_always durability)";
31514
31514
  const kernelStat = opts?.statBroker ?? defaultKernelStatBroker;
@@ -31576,8 +31576,8 @@ function defaultKernelStatBroker(p) {
31576
31576
  return { kind: "ok-with-stat", ino: inoStr, size };
31577
31577
  }
31578
31578
  function probeAutoUnlockBlob(home2) {
31579
- const blobPath = join55(home2, ".switchroom", "vault-auto-unlock");
31580
- if (!existsSync54(blobPath)) {
31579
+ const blobPath = join56(home2, ".switchroom", "vault-auto-unlock");
31580
+ if (!existsSync55(blobPath)) {
31581
31581
  return {
31582
31582
  name: "vault-broker: auto-unlock blob",
31583
31583
  status: "warn",
@@ -31585,7 +31585,7 @@ function probeAutoUnlockBlob(home2) {
31585
31585
  fix: "Run `switchroom vault broker enable-auto-unlock` to seal the blob with the current passphrase + machine-id"
31586
31586
  };
31587
31587
  }
31588
- const sz = statSync23(blobPath).size;
31588
+ const sz = statSync24(blobPath).size;
31589
31589
  if (sz === 0) {
31590
31590
  return {
31591
31591
  name: "vault-broker: auto-unlock blob",
@@ -31601,7 +31601,7 @@ function probeAutoUnlockBlob(home2) {
31601
31601
  };
31602
31602
  }
31603
31603
  function probeMachineIdMount() {
31604
- const hostExists = existsSync54("/etc/machine-id");
31604
+ const hostExists = existsSync55("/etc/machine-id");
31605
31605
  if (!hostExists) {
31606
31606
  return {
31607
31607
  name: "vault-broker: machine-id passthrough",
@@ -31680,25 +31680,25 @@ import { execSync as execSync3, spawnSync as spawnSync8 } from "node:child_proce
31680
31680
  import {
31681
31681
  accessSync as accessSync2,
31682
31682
  constants as fsConstants5,
31683
- existsSync as existsSync55,
31684
- lstatSync as lstatSync5,
31683
+ existsSync as existsSync56,
31684
+ lstatSync as lstatSync6,
31685
31685
  mkdirSync as mkdirSync30,
31686
31686
  readFileSync as readFileSync49,
31687
- readdirSync as readdirSync20,
31688
- statSync as statSync24
31687
+ readdirSync as readdirSync21,
31688
+ statSync as statSync25
31689
31689
  } from "node:fs";
31690
- import { dirname as dirname12, join as join56, resolve as resolve32 } from "node:path";
31690
+ import { dirname as dirname13, join as join57, resolve as resolve32 } from "node:path";
31691
31691
  import { createPublicKey, createPrivateKey } from "node:crypto";
31692
31692
  function findInNvm(bin) {
31693
- const nvmRoot = join56(process.env.HOME ?? "", ".nvm", "versions", "node");
31694
- if (!existsSync55(nvmRoot))
31693
+ const nvmRoot = join57(process.env.HOME ?? "", ".nvm", "versions", "node");
31694
+ if (!existsSync56(nvmRoot))
31695
31695
  return null;
31696
31696
  try {
31697
- const versions = readdirSync20(nvmRoot).sort().reverse();
31697
+ const versions = readdirSync21(nvmRoot).sort().reverse();
31698
31698
  for (const v of versions) {
31699
- const candidate = join56(nvmRoot, v, "bin", bin);
31699
+ const candidate = join57(nvmRoot, v, "bin", bin);
31700
31700
  try {
31701
- const s = statSync24(candidate);
31701
+ const s = statSync25(candidate);
31702
31702
  if (s.isFile() || s.isSymbolicLink()) {
31703
31703
  return candidate;
31704
31704
  }
@@ -31861,21 +31861,21 @@ function findChromium(homeDir = process.env.HOME ?? "", envBrowsersPath = proces
31861
31861
  if (envBrowsersPath && envBrowsersPath.length > 0) {
31862
31862
  cacheLocations.push(envBrowsersPath);
31863
31863
  }
31864
- cacheLocations.push(join56(homeDir, ".cache", "ms-playwright"));
31864
+ cacheLocations.push(join57(homeDir, ".cache", "ms-playwright"));
31865
31865
  for (const cacheDir of cacheLocations) {
31866
- if (!existsSync55(cacheDir))
31866
+ if (!existsSync56(cacheDir))
31867
31867
  continue;
31868
31868
  try {
31869
- const entries = readdirSync20(cacheDir).filter((e) => e.startsWith("chromium"));
31869
+ const entries = readdirSync21(cacheDir).filter((e) => e.startsWith("chromium"));
31870
31870
  for (const entry of entries) {
31871
31871
  const candidates2 = [
31872
- join56(cacheDir, entry, "chrome-linux64", "chrome"),
31873
- join56(cacheDir, entry, "chrome-linux", "chrome"),
31874
- join56(cacheDir, entry, "chrome-linux64", "headless_shell"),
31875
- join56(cacheDir, entry, "chrome-linux", "headless_shell")
31872
+ join57(cacheDir, entry, "chrome-linux64", "chrome"),
31873
+ join57(cacheDir, entry, "chrome-linux", "chrome"),
31874
+ join57(cacheDir, entry, "chrome-linux64", "headless_shell"),
31875
+ join57(cacheDir, entry, "chrome-linux", "headless_shell")
31876
31876
  ];
31877
31877
  for (const path4 of candidates2) {
31878
- if (existsSync55(path4))
31878
+ if (existsSync56(path4))
31879
31879
  return path4;
31880
31880
  }
31881
31881
  }
@@ -31995,8 +31995,8 @@ function checkUserDeclaredMcps(name, agentConfig, config, renderedMcpServers) {
31995
31995
  function checkLegacyState() {
31996
31996
  const results = [];
31997
31997
  const h = process.env.HOME ?? "/root";
31998
- const clerkDir = join56(h, LEGACY_STATE_DIR);
31999
- const clerkPresent = existsSync55(clerkDir);
31998
+ const clerkDir = join57(h, LEGACY_STATE_DIR);
31999
+ const clerkPresent = existsSync56(clerkDir);
32000
32000
  results.push({
32001
32001
  name: "legacy ~/.clerk state",
32002
32002
  status: clerkPresent ? "warn" : "ok",
@@ -32005,10 +32005,10 @@ function checkLegacyState() {
32005
32005
  fix: "Legacy state detected. Run `mv ~/.clerk ~/.switchroom` and rename " + "any top-level `clerk:` key in switchroom.yaml to `switchroom:`. " + "This back-compat shim is REMOVED in v0.13.0 \u2014 no automatic " + "migration exists."
32006
32006
  } : {}
32007
32007
  });
32008
- const legacySock = join56(h, ".switchroom", "vault-broker.sock");
32008
+ const legacySock = join57(h, ".switchroom", "vault-broker.sock");
32009
32009
  let sockStat = null;
32010
32010
  try {
32011
- sockStat = lstatSync5(legacySock);
32011
+ sockStat = lstatSync6(legacySock);
32012
32012
  } catch {}
32013
32013
  if (sockStat) {
32014
32014
  results.push({
@@ -32126,7 +32126,7 @@ function checkVault(config) {
32126
32126
  detail: "Approval auth: passphrase (two-factor)"
32127
32127
  };
32128
32128
  const pairsResult = checkVaultBrokerSocketPairs(config);
32129
- if (!existsSync55(vaultPath)) {
32129
+ if (!existsSync56(vaultPath)) {
32130
32130
  return [
32131
32131
  postureResult,
32132
32132
  {
@@ -32306,8 +32306,8 @@ async function checkHindsight(config) {
32306
32306
  }
32307
32307
  function checkPendingRetainsQueue(dir) {
32308
32308
  const home2 = process.env.HOME ?? "";
32309
- const pendingDir = dir ?? process.env.HINDSIGHT_PENDING_DIR ?? join56(home2, ".hindsight", "pending-retains");
32310
- if (!existsSync55(pendingDir)) {
32309
+ const pendingDir = dir ?? process.env.HINDSIGHT_PENDING_DIR ?? join57(home2, ".hindsight", "pending-retains");
32310
+ if (!existsSync56(pendingDir)) {
32311
32311
  return {
32312
32312
  name: "pending-retains queue",
32313
32313
  status: "ok",
@@ -32316,7 +32316,7 @@ function checkPendingRetainsQueue(dir) {
32316
32316
  }
32317
32317
  let names;
32318
32318
  try {
32319
- names = readdirSync20(pendingDir);
32319
+ names = readdirSync21(pendingDir);
32320
32320
  } catch (err) {
32321
32321
  return {
32322
32322
  name: "pending-retains queue",
@@ -32378,7 +32378,7 @@ function tryReadHostFile(path4) {
32378
32378
  }
32379
32379
  }
32380
32380
  function parseEnvFile(path4) {
32381
- if (!existsSync55(path4))
32381
+ if (!existsSync56(path4))
32382
32382
  return {};
32383
32383
  let content;
32384
32384
  try {
@@ -32437,7 +32437,7 @@ async function checkTelegram(config) {
32437
32437
  const plugin = agentConfig.channels?.telegram?.plugin ?? "switchroom";
32438
32438
  if (plugin !== "switchroom")
32439
32439
  continue;
32440
- const envPath = join56(agentsDir, name, "telegram", ".env");
32440
+ const envPath = join57(agentsDir, name, "telegram", ".env");
32441
32441
  const read = tryReadHostFile(envPath);
32442
32442
  if (read.kind === "eacces") {
32443
32443
  results.push({
@@ -32489,7 +32489,7 @@ async function checkTelegram(config) {
32489
32489
  }
32490
32490
  function checkStartShStale(agentName, startShPath) {
32491
32491
  const label = `${agentName}: start.sh scheduler block`;
32492
- if (!existsSync55(startShPath)) {
32492
+ if (!existsSync56(startShPath)) {
32493
32493
  return {
32494
32494
  name: label,
32495
32495
  status: "warn",
@@ -32520,10 +32520,10 @@ function checkStartShStale(agentName, startShPath) {
32520
32520
  }
32521
32521
  function checkLeakedHomeSwitchroom(agentName, agentDir) {
32522
32522
  const label = `${agentName}: $HOME/.switchroom symlink (#910)`;
32523
- const path4 = join56(agentDir, "home", ".switchroom");
32523
+ const path4 = join57(agentDir, "home", ".switchroom");
32524
32524
  let stats;
32525
32525
  try {
32526
- stats = lstatSync5(path4);
32526
+ stats = lstatSync6(path4);
32527
32527
  } catch (err) {
32528
32528
  if (err.code === "ENOENT") {
32529
32529
  return {
@@ -32557,8 +32557,8 @@ function checkLeakedHomeSwitchroom(agentName, agentDir) {
32557
32557
  }
32558
32558
  function checkRepoHygiene(repoRoot) {
32559
32559
  const results = [];
32560
- const exportDir = join56(repoRoot, "clerk-export");
32561
- if (existsSync55(exportDir)) {
32560
+ const exportDir = join57(repoRoot, "clerk-export");
32561
+ if (existsSync56(exportDir)) {
32562
32562
  results.push({
32563
32563
  name: "repo hygiene: clerk-export/ on disk (#1072)",
32564
32564
  status: "warn",
@@ -32566,8 +32566,8 @@ function checkRepoHygiene(repoRoot) {
32566
32566
  fix: `Run scripts/migrate-clerk-export-to-vault.sh to move the bundle ` + `into the vault, then delete the on-disk copy.`
32567
32567
  });
32568
32568
  }
32569
- const knownTarball = join56(repoRoot, "clerk-export-with-secrets.tar.gz");
32570
- if (existsSync55(knownTarball)) {
32569
+ const knownTarball = join57(repoRoot, "clerk-export-with-secrets.tar.gz");
32570
+ if (existsSync56(knownTarball)) {
32571
32571
  results.push({
32572
32572
  name: "repo hygiene: clerk-export-with-secrets.tar.gz on disk (#1072)",
32573
32573
  status: "warn",
@@ -32576,7 +32576,7 @@ function checkRepoHygiene(repoRoot) {
32576
32576
  });
32577
32577
  }
32578
32578
  try {
32579
- const entries = readdirSync20(repoRoot);
32579
+ const entries = readdirSync21(repoRoot);
32580
32580
  for (const name of entries) {
32581
32581
  if (name === "clerk-export-with-secrets.tar.gz")
32582
32582
  continue;
@@ -32584,7 +32584,7 @@ function checkRepoHygiene(repoRoot) {
32584
32584
  results.push({
32585
32585
  name: `repo hygiene: ${name} on disk (#1072)`,
32586
32586
  status: "warn",
32587
- detail: `${join56(repoRoot, name)} matches the *-with-secrets*.tar.gz ` + `pattern. Likely contains real credentials.`,
32587
+ detail: `${join57(repoRoot, name)} matches the *-with-secrets*.tar.gz ` + `pattern. Likely contains real credentials.`,
32588
32588
  fix: `Inspect, migrate any secrets into the vault, then delete the ` + `archive.`
32589
32589
  });
32590
32590
  }
@@ -32607,10 +32607,10 @@ function checkRepoHygiene(repoRoot) {
32607
32607
  }
32608
32608
  function isSwitchroomCheckout(dir) {
32609
32609
  try {
32610
- if (!existsSync55(join56(dir, ".git")))
32610
+ if (!existsSync56(join57(dir, ".git")))
32611
32611
  return false;
32612
- const pkgPath = join56(dir, "package.json");
32613
- if (!existsSync55(pkgPath))
32612
+ const pkgPath = join57(dir, "package.json");
32613
+ if (!existsSync56(pkgPath))
32614
32614
  return false;
32615
32615
  const pkg = JSON.parse(readFileSync49(pkgPath, "utf-8"));
32616
32616
  return pkg.name === "switchroom";
@@ -32625,7 +32625,7 @@ function checkAgents(config, configPath) {
32625
32625
  const authStatuses = getAllAuthStatuses(config);
32626
32626
  for (const [name, agentConfig] of Object.entries(config.agents)) {
32627
32627
  const agentDir = resolve32(agentsDir, name);
32628
- if (!existsSync55(agentDir)) {
32628
+ if (!existsSync56(agentDir)) {
32629
32629
  results.push({
32630
32630
  name: `${name}: scaffold`,
32631
32631
  status: "fail",
@@ -32646,7 +32646,7 @@ function checkAgents(config, configPath) {
32646
32646
  fix: `Rotate the bot token (e.g. via \`switchroom vault\`), then run ` + `\`switchroom agent unquarantine ${name}\` and \`switchroom agent restart ${name}\``
32647
32647
  });
32648
32648
  }
32649
- results.push(checkStartShStale(name, join56(agentDir, "start.sh")));
32649
+ results.push(checkStartShStale(name, join57(agentDir, "start.sh")));
32650
32650
  results.push(checkLeakedHomeSwitchroom(name, agentDir));
32651
32651
  const status = statuses[name];
32652
32652
  const active = status?.active ?? "unknown";
@@ -32723,8 +32723,8 @@ function checkAgents(config, configPath) {
32723
32723
  }
32724
32724
  }
32725
32725
  if (agentConfig.channels?.telegram?.plugin === "switchroom") {
32726
- const mcpJsonPath = join56(agentDir, ".mcp.json");
32727
- if (!existsSync55(mcpJsonPath)) {
32726
+ const mcpJsonPath = join57(agentDir, ".mcp.json");
32727
+ if (!existsSync56(mcpJsonPath)) {
32728
32728
  results.push({
32729
32729
  name: `${name}: .mcp.json`,
32730
32730
  status: "fail",
@@ -32810,7 +32810,7 @@ function mffEnvPath(config) {
32810
32810
  return agent ? resolve32(home2, ".switchroom/credentials", agent, "my-family-finance/.env") : resolve32(home2, ".switchroom/credentials/my-family-finance/.env");
32811
32811
  }
32812
32812
  function mffEnvState(envPath) {
32813
- if (!existsSync55(envPath))
32813
+ if (!existsSync56(envPath))
32814
32814
  return "absent";
32815
32815
  try {
32816
32816
  accessSync2(envPath, fsConstants5.R_OK);
@@ -32828,7 +32828,7 @@ function checkMffVaultKeyPresent(passphrase, vaultPath) {
32828
32828
  fix: "Export SWITCHROOM_VAULT_PASSPHRASE to enable MFF vault probes"
32829
32829
  };
32830
32830
  }
32831
- if (!existsSync55(vaultPath)) {
32831
+ if (!existsSync56(vaultPath)) {
32832
32832
  return {
32833
32833
  name: "mff: vault key present",
32834
32834
  status: "fail",
@@ -32881,7 +32881,7 @@ function deriveEd25519PublicKeyBytes(keyMaterial) {
32881
32881
  }
32882
32882
  }
32883
32883
  function checkMffVaultKeyFormat(passphrase, vaultPath) {
32884
- if (!passphrase || !existsSync55(vaultPath)) {
32884
+ if (!passphrase || !existsSync56(vaultPath)) {
32885
32885
  return {
32886
32886
  name: "mff: vault key format",
32887
32887
  status: "warn",
@@ -33024,9 +33024,9 @@ async function checkMffAuthFlow(envPath = mffEnvPath(), timeoutMs = 8000) {
33024
33024
  detail: "skipped (MFF_API_URL not set)"
33025
33025
  };
33026
33026
  }
33027
- const credDir = dirname12(envPath);
33028
- const authScript = join56(credDir, "claude-auth.py");
33029
- if (!existsSync55(authScript)) {
33027
+ const credDir = dirname13(envPath);
33028
+ const authScript = join57(credDir, "claude-auth.py");
33029
+ if (!existsSync56(authScript)) {
33030
33030
  return {
33031
33031
  name: "mff: auth flow",
33032
33032
  status: "warn",
@@ -49937,14 +49937,14 @@ var {
49937
49937
  } = import__.default;
49938
49938
 
49939
49939
  // src/build-info.ts
49940
- var VERSION = "0.14.92";
49941
- var COMMIT_SHA = "cd0b9973";
49940
+ var VERSION = "0.15.0";
49941
+ var COMMIT_SHA = "5841c1d5";
49942
49942
 
49943
49943
  // src/cli/agent.ts
49944
49944
  init_source();
49945
- import { join as join17, resolve as resolve21 } from "node:path";
49946
- import { rmSync as rmSync9, existsSync as existsSync26, readFileSync as readFileSync22, writeFileSync as writeFileSync13 } from "node:fs";
49947
- import { homedir as homedir6 } from "node:os";
49945
+ import { join as join18, resolve as resolve21 } from "node:path";
49946
+ import { rmSync as rmSync9, existsSync as existsSync27, readFileSync as readFileSync22, writeFileSync as writeFileSync13 } from "node:fs";
49947
+ import { homedir as homedir7 } from "node:os";
49948
49948
 
49949
49949
  // src/agents/scheduler-state.ts
49950
49950
  import { closeSync, openSync, readSync, statSync } from "node:fs";
@@ -53465,24 +53465,179 @@ function buildAccessJson2(agentConfig, telegramConfig, resolvedTopicId, userId)
53465
53465
  `;
53466
53466
  }
53467
53467
 
53468
+ // src/cli/write-compose.ts
53469
+ init_compose();
53470
+ import { chownSync as chownSync2 } from "node:fs";
53471
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
53472
+ import { homedir as homedir5 } from "node:os";
53473
+ import { dirname as dirname3 } from "node:path";
53474
+
53475
+ // src/config/release-resolve.ts
53476
+ function resolveImageTag(release) {
53477
+ if (!release)
53478
+ return "latest";
53479
+ if (release.pin)
53480
+ return release.pin;
53481
+ if (release.channel)
53482
+ return release.channel;
53483
+ return "latest";
53484
+ }
53485
+ function resolveRelease(opts) {
53486
+ if (opts.override)
53487
+ return opts.override;
53488
+ if (opts.perAgent)
53489
+ return opts.perAgent;
53490
+ if (opts.root)
53491
+ return opts.root;
53492
+ return;
53493
+ }
53494
+
53495
+ // src/cli/operator-uid.ts
53496
+ import {
53497
+ chownSync,
53498
+ existsSync as existsSync15,
53499
+ lstatSync as lstatSync4,
53500
+ readdirSync as readdirSync7,
53501
+ realpathSync as realpathSync3,
53502
+ statSync as statSync8
53503
+ } from "node:fs";
53504
+ import { join as join10 } from "node:path";
53505
+ function resolveOperatorUid() {
53506
+ const sudoUid = process.env.SUDO_UID;
53507
+ if (sudoUid !== undefined) {
53508
+ const parsed = parseInt(sudoUid, 10);
53509
+ if (Number.isFinite(parsed) && parsed > 0)
53510
+ return parsed;
53511
+ }
53512
+ if (typeof process.getuid === "function") {
53513
+ const uid = process.getuid();
53514
+ if (uid > 0)
53515
+ return uid;
53516
+ }
53517
+ return;
53518
+ }
53519
+ function operatorOwnedPaths(home2) {
53520
+ const root = join10(home2, ".switchroom");
53521
+ return [
53522
+ join10(root, "vault"),
53523
+ join10(root, "vault-auto-unlock"),
53524
+ join10(root, "vault-audit.log"),
53525
+ join10(root, "host-control-audit.log"),
53526
+ join10(root, "accounts"),
53527
+ join10(root, "compose")
53528
+ ];
53529
+ }
53530
+ function restoreOperatorOwnership(home2, operatorUid, deps = {}) {
53531
+ const chown = deps.chown ?? ((p, u, g) => chownSync(p, u, g));
53532
+ const exists = deps.exists ?? ((p) => existsSync15(p));
53533
+ const isSymlink = deps.isSymlink ?? ((p) => {
53534
+ try {
53535
+ return lstatSync4(p).isSymbolicLink();
53536
+ } catch {
53537
+ return false;
53538
+ }
53539
+ });
53540
+ const isDir = deps.isDir ?? ((p) => {
53541
+ try {
53542
+ return statSync8(p).isDirectory();
53543
+ } catch {
53544
+ return false;
53545
+ }
53546
+ });
53547
+ const realpath = deps.realpath ?? ((p) => {
53548
+ try {
53549
+ return realpathSync3(p);
53550
+ } catch {
53551
+ return p;
53552
+ }
53553
+ });
53554
+ const readdir = deps.readdir ?? ((p) => {
53555
+ try {
53556
+ return readdirSync7(p);
53557
+ } catch {
53558
+ return [];
53559
+ }
53560
+ });
53561
+ const chowned = [];
53562
+ const seen = new Set;
53563
+ const visit = (path) => {
53564
+ if (!exists(path))
53565
+ return;
53566
+ const target = isSymlink(path) ? realpath(path) : path;
53567
+ if (seen.has(target))
53568
+ return;
53569
+ seen.add(target);
53570
+ try {
53571
+ chown(target, operatorUid, operatorUid);
53572
+ chowned.push(target);
53573
+ } catch {}
53574
+ if (isDir(target)) {
53575
+ for (const entry of readdir(target)) {
53576
+ visit(join10(target, entry));
53577
+ }
53578
+ }
53579
+ };
53580
+ for (const p of operatorOwnedPaths(home2))
53581
+ visit(p);
53582
+ return chowned;
53583
+ }
53584
+
53585
+ // src/cli/write-compose.ts
53586
+ var AGENT_IMAGE_TAG_RE = /image:\s*\S*switchroom-agent:(\S+)/;
53587
+ async function writeComposeFile(opts) {
53588
+ const release = resolveRelease({ override: opts.releaseOverride, root: opts.config.release });
53589
+ const imageTag = resolveImageTag(release);
53590
+ const operatorUid = resolveOperatorUid();
53591
+ const content = generateCompose({
53592
+ config: opts.config,
53593
+ imageTag,
53594
+ buildMode: opts.buildMode ?? "pull",
53595
+ buildContext: opts.buildContext,
53596
+ homeDir: homedir5(),
53597
+ switchroomConfigPath: opts.switchroomConfigPath,
53598
+ operatorUid
53599
+ });
53600
+ let previous = null;
53601
+ try {
53602
+ previous = await readFile(opts.composePath, "utf8");
53603
+ } catch {
53604
+ previous = null;
53605
+ }
53606
+ const previousImageTag = previous ? AGENT_IMAGE_TAG_RE.exec(previous)?.[1] ?? null : null;
53607
+ await mkdir(dirname3(opts.composePath), { recursive: true });
53608
+ await writeFile(opts.composePath, content, { encoding: "utf8", mode: 384 });
53609
+ if (operatorUid !== undefined && process.geteuid?.() === 0) {
53610
+ try {
53611
+ chownSync2(opts.composePath, operatorUid, operatorUid);
53612
+ } catch {}
53613
+ }
53614
+ return {
53615
+ composePath: opts.composePath,
53616
+ imageTag,
53617
+ bytes: Buffer.byteLength(content, "utf8"),
53618
+ changed: previous !== content,
53619
+ previousImageTag
53620
+ };
53621
+ }
53622
+
53468
53623
  // src/cli/agent.ts
53469
53624
  init_lifecycle();
53470
53625
  init_merge();
53471
53626
 
53472
53627
  // src/agents/in-flight.ts
53473
- import { readdirSync as readdirSync7, statSync as statSync8 } from "node:fs";
53628
+ import { readdirSync as readdirSync8, statSync as statSync9 } from "node:fs";
53474
53629
  import { resolve as resolve14 } from "node:path";
53475
53630
  var DEFAULT_RECENCY_MS = 30000;
53476
53631
  function safeReaddir(path) {
53477
53632
  try {
53478
- return readdirSync7(path);
53633
+ return readdirSync8(path);
53479
53634
  } catch {
53480
53635
  return [];
53481
53636
  }
53482
53637
  }
53483
53638
  function safeMtimeMs(path) {
53484
53639
  try {
53485
- return statSync8(path).mtimeMs;
53640
+ return statSync9(path).mtimeMs;
53486
53641
  } catch {
53487
53642
  return 0;
53488
53643
  }
@@ -53501,7 +53656,7 @@ function collectJsonl(root, maxDepth = 4) {
53501
53656
  const full = resolve14(dir, entry);
53502
53657
  let isDir = false;
53503
53658
  try {
53504
- isDir = statSync8(full).isDirectory();
53659
+ isDir = statSync9(full).isDirectory();
53505
53660
  } catch {
53506
53661
  continue;
53507
53662
  }
@@ -53690,13 +53845,13 @@ function spinner(message) {
53690
53845
  }
53691
53846
 
53692
53847
  // src/agents/status.ts
53693
- import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync10 } from "node:fs";
53694
- import { join as join12 } from "node:path";
53848
+ import { existsSync as existsSync19, readFileSync as readFileSync17, statSync as statSync11 } from "node:fs";
53849
+ import { join as join13 } from "node:path";
53695
53850
  import { execFileSync as execFileSync9 } from "node:child_process";
53696
53851
 
53697
53852
  // src/agents/handoff-summarizer.ts
53698
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, renameSync as renameSync5, mkdirSync as mkdirSync13, existsSync as existsSync16, statSync as statSync9, readdirSync as readdirSync8 } from "node:fs";
53699
- import { join as join11 } from "node:path";
53853
+ import { readFileSync as readFileSync15, writeFileSync as writeFileSync8, renameSync as renameSync5, mkdirSync as mkdirSync13, existsSync as existsSync17, statSync as statSync10, readdirSync as readdirSync9 } from "node:fs";
53854
+ import { join as join12 } from "node:path";
53700
53855
  var DEFAULT_MAX_TURNS = 50;
53701
53856
  var TOPIC_MAX_CHARS = 117;
53702
53857
  var TURN_TEXT_MAX_CHARS = 1200;
@@ -53831,8 +53986,8 @@ function clampTopic(s) {
53831
53986
  }
53832
53987
  function writeSidecarsAtomic(agentDir, briefing, topic) {
53833
53988
  mkdirSync13(agentDir, { recursive: true });
53834
- const handoffPath = join11(agentDir, ".handoff.md");
53835
- const topicPath = join11(agentDir, ".handoff-topic");
53989
+ const handoffPath = join12(agentDir, ".handoff.md");
53990
+ const topicPath = join12(agentDir, ".handoff-topic");
53836
53991
  const handoffTmp = handoffPath + ".tmp";
53837
53992
  const topicTmp = topicPath + ".tmp";
53838
53993
  writeFileSync8(handoffTmp, briefing, "utf-8");
@@ -53893,22 +54048,22 @@ async function mirrorToHindsight(briefing, opts) {
53893
54048
  }
53894
54049
  }
53895
54050
  function findLatestSessionJsonl(claudeConfigDir) {
53896
- const projects = join11(claudeConfigDir, "projects");
53897
- if (!existsSync16(projects))
54051
+ const projects = join12(claudeConfigDir, "projects");
54052
+ if (!existsSync17(projects))
53898
54053
  return null;
53899
54054
  let latest = null;
53900
54055
  const walk = (dir) => {
53901
54056
  let entries;
53902
54057
  try {
53903
- entries = readdirSync8(dir);
54058
+ entries = readdirSync9(dir);
53904
54059
  } catch {
53905
54060
  return;
53906
54061
  }
53907
54062
  for (const name of entries) {
53908
- const full = join11(dir, name);
54063
+ const full = join12(dir, name);
53909
54064
  let st;
53910
54065
  try {
53911
- st = statSync9(full);
54066
+ st = statSync10(full);
53912
54067
  } catch {
53913
54068
  continue;
53914
54069
  }
@@ -53928,9 +54083,9 @@ function findLatestSessionJsonl(claudeConfigDir) {
53928
54083
  }
53929
54084
 
53930
54085
  // src/agents/perf.ts
53931
- import { existsSync as existsSync17, readFileSync as readFileSync16 } from "node:fs";
54086
+ import { existsSync as existsSync18, readFileSync as readFileSync16 } from "node:fs";
53932
54087
  function readTurnUsages(jsonlPath, lastN) {
53933
- if (!existsSync17(jsonlPath))
54088
+ if (!existsSync18(jsonlPath))
53934
54089
  return [];
53935
54090
  if (lastN <= 0)
53936
54091
  return [];
@@ -54241,10 +54396,10 @@ async function buildAgentStatusReport(inputs) {
54241
54396
  };
54242
54397
  }
54243
54398
  }
54244
- const logPath = join12(inputs.agentDir, "telegram", "gateway.log");
54399
+ const logPath = join13(inputs.agentDir, "telegram", "gateway.log");
54245
54400
  const logContent = inputs.readGatewayLog(logPath);
54246
54401
  const polling = buildPollingStatus(logContent);
54247
- const historyDbPath = join12(inputs.agentDir, "telegram", "history.db");
54402
+ const historyDbPath = join13(inputs.agentDir, "telegram", "history.db");
54248
54403
  const messagesResult = inputs.getLastMessages(historyDbPath);
54249
54404
  const messages = buildMessageStatus(messagesResult);
54250
54405
  const checks = [
@@ -54339,10 +54494,10 @@ function formatWindowFromIso(first, last) {
54339
54494
  return `${f} .. ${l}`;
54340
54495
  }
54341
54496
  function readLogFile(logPath) {
54342
- if (!existsSync18(logPath))
54497
+ if (!existsSync19(logPath))
54343
54498
  return null;
54344
54499
  try {
54345
- const stat = statSync10(logPath);
54500
+ const stat = statSync11(logPath);
54346
54501
  const cap = 256 * 1024;
54347
54502
  if (stat.size <= cap) {
54348
54503
  return readFileSync17(logPath, "utf-8");
@@ -54361,7 +54516,7 @@ function readLogFile(logPath) {
54361
54516
  }
54362
54517
  }
54363
54518
  function readLastMessages(historyDbPath) {
54364
- if (!existsSync18(historyDbPath)) {
54519
+ if (!existsSync19(historyDbPath)) {
54365
54520
  return {
54366
54521
  lastInboundTs: null,
54367
54522
  lastOutboundTs: null,
@@ -54522,7 +54677,7 @@ function defaultStatusInputs(params) {
54522
54677
  }
54523
54678
  function readCacheTelemetry(agentDir) {
54524
54679
  try {
54525
- const claudeConfigDir = join12(agentDir, ".claude");
54680
+ const claudeConfigDir = join13(agentDir, ".claude");
54526
54681
  const jsonl = findLatestSessionJsonl(claudeConfigDir);
54527
54682
  if (!jsonl)
54528
54683
  return null;
@@ -54546,7 +54701,7 @@ function readCacheTelemetry(agentDir) {
54546
54701
  // src/agents/create-orchestrator.ts
54547
54702
  init_loader();
54548
54703
  import { resolve as resolve16 } from "node:path";
54549
- import { existsSync as existsSync21, rmSync as rmSync6 } from "node:fs";
54704
+ import { existsSync as existsSync22, rmSync as rmSync6 } from "node:fs";
54550
54705
  init_lifecycle();
54551
54706
  init_manager();
54552
54707
 
@@ -54653,7 +54808,7 @@ async function createAgent(opts) {
54653
54808
  resolve16(cwd, "switchroom.yml")
54654
54809
  ];
54655
54810
  for (const c of candidates) {
54656
- if (existsSync21(c))
54811
+ if (existsSync22(c))
54657
54812
  return c;
54658
54813
  }
54659
54814
  throw new Error("switchroom.yaml not found. Pass configPath or run from the project root.");
@@ -54716,14 +54871,14 @@ async function completeCreation(name, code, opts = {}) {
54716
54871
  const cwd = process.cwd();
54717
54872
  const candidates = [resolve16(cwd, "switchroom.yaml"), resolve16(cwd, "switchroom.yml")];
54718
54873
  for (const c of candidates)
54719
- if (existsSync21(c))
54874
+ if (existsSync22(c))
54720
54875
  return c;
54721
54876
  throw new Error("switchroom.yaml not found. Pass configPath option.");
54722
54877
  })();
54723
54878
  const config = loadConfig(configPath);
54724
54879
  const agentsDir = resolveAgentsDir(config);
54725
54880
  const agentDir = resolve16(agentsDir, name);
54726
- if (!existsSync21(agentDir)) {
54881
+ if (!existsSync22(agentDir)) {
54727
54882
  throw new Error(`Agent dir not found: ${agentDir}. Run createAgent first.`);
54728
54883
  }
54729
54884
  const authCodeResult = submitAuthCode(name, agentDir, code, undefined, opts.pollTimeoutMs ? { pollTimeoutMs: opts.pollTimeoutMs } : {});
@@ -54762,8 +54917,8 @@ async function completeCreation(name, code, opts = {}) {
54762
54917
  }
54763
54918
 
54764
54919
  // src/agents/add-orchestrator.ts
54765
- import { resolve as resolve18, join as join15 } from "node:path";
54766
- import { existsSync as existsSync23, rmSync as rmSync7, statSync as statSync14 } from "node:fs";
54920
+ import { resolve as resolve18, join as join16 } from "node:path";
54921
+ import { existsSync as existsSync24, rmSync as rmSync7, statSync as statSync15 } from "node:fs";
54767
54922
  import { execFileSync as execFileSync12 } from "node:child_process";
54768
54923
 
54769
54924
  // src/setup/botfather-walkthrough.ts
@@ -54854,7 +55009,7 @@ function enforceUsername(username, agentSlug, expectedUsername, loose, warn) {
54854
55009
  }
54855
55010
 
54856
55011
  // src/setup/profile-picker.ts
54857
- import { existsSync as existsSync22, readdirSync as readdirSync11, statSync as statSync13 } from "node:fs";
55012
+ import { existsSync as existsSync23, readdirSync as readdirSync12, statSync as statSync14 } from "node:fs";
54858
55013
  import { resolve as resolve17 } from "node:path";
54859
55014
  var PROFILE_GLOSSES = {
54860
55015
  default: "minimal baseline \u2014 generic chat helper, no opinion.",
@@ -54866,13 +55021,13 @@ var DEFAULT_MAX_ATTEMPTS2 = 3;
54866
55021
  var PROFILES_ROOT2 = resolve17(import.meta.dirname, "../../profiles");
54867
55022
  function defaultListProfileSkills(profileName) {
54868
55023
  const skillsDir = resolve17(PROFILES_ROOT2, profileName, "skills");
54869
- if (!existsSync22(skillsDir)) {
55024
+ if (!existsSync23(skillsDir)) {
54870
55025
  return [];
54871
55026
  }
54872
55027
  try {
54873
- return readdirSync11(skillsDir).filter((entry) => {
55028
+ return readdirSync12(skillsDir).filter((entry) => {
54874
55029
  try {
54875
- return statSync13(resolve17(skillsDir, entry)).isDirectory();
55030
+ return statSync14(resolve17(skillsDir, entry)).isDirectory();
54876
55031
  } catch {
54877
55032
  return false;
54878
55033
  }
@@ -55153,7 +55308,7 @@ function runFinalPreflight(inputs) {
55153
55308
  const { name, agentDir, expectedUserId, isUnitActive, configPath } = inputs;
55154
55309
  const unitPath = resolve18(process.env.HOME ?? "/root", ".config/systemd/user", `switchroom-${name}.service`);
55155
55310
  let autoaccept = { ok: false, detail: `unit not found at ${unitPath}` };
55156
- if (existsSync23(unitPath)) {
55311
+ if (existsSync24(unitPath)) {
55157
55312
  const fs2 = __require("node:fs");
55158
55313
  const content = fs2.readFileSync(unitPath, "utf-8");
55159
55314
  if (content.includes("expect") || content.includes("autoaccept")) {
@@ -55172,7 +55327,7 @@ function runFinalPreflight(inputs) {
55172
55327
  }
55173
55328
  const envPath = resolve18(agentDir, "telegram", ".env");
55174
55329
  let token = { ok: false, detail: `telegram/.env missing at ${envPath}` };
55175
- if (existsSync23(envPath)) {
55330
+ if (existsSync24(envPath)) {
55176
55331
  const fs2 = __require("node:fs");
55177
55332
  const content = fs2.readFileSync(envPath, "utf-8");
55178
55333
  if (/TELEGRAM_BOT_TOKEN=\S+/.test(content)) {
@@ -55200,7 +55355,7 @@ function runFinalPreflight(inputs) {
55200
55355
  }
55201
55356
  const accessPath = resolve18(agentDir, "telegram", "access.json");
55202
55357
  let access;
55203
- if (!existsSync23(accessPath)) {
55358
+ if (!existsSync24(accessPath)) {
55204
55359
  access = {
55205
55360
  ok: false,
55206
55361
  detail: `access.json missing at ${accessPath}`
@@ -55227,7 +55382,7 @@ function runFinalPreflight(inputs) {
55227
55382
  }
55228
55383
  const settingsPath = resolve18(agentDir, ".claude", "settings.json");
55229
55384
  let mcp;
55230
- if (!existsSync23(settingsPath)) {
55385
+ if (!existsSync24(settingsPath)) {
55231
55386
  mcp = {
55232
55387
  ok: false,
55233
55388
  detail: `.claude/settings.json missing at ${settingsPath}. ` + `Fix: switchroom agent reconcile ${name}`
@@ -55261,7 +55416,7 @@ function runFinalPreflight(inputs) {
55261
55416
  ok: true,
55262
55417
  detail: "skipped (no switchroom.yaml path supplied)"
55263
55418
  };
55264
- } else if (!existsSync23(configPath)) {
55419
+ } else if (!existsSync24(configPath)) {
55265
55420
  vaultMgd = {
55266
55421
  ok: false,
55267
55422
  detail: `switchroom.yaml not found at ${configPath}`
@@ -55307,7 +55462,7 @@ function runFinalPreflight(inputs) {
55307
55462
  }
55308
55463
  function pruneBundledSkills(agentDir, keep, scope) {
55309
55464
  const skillsDir = resolve18(agentDir, ".claude", "skills");
55310
- if (!existsSync23(skillsDir)) {
55465
+ if (!existsSync24(skillsDir)) {
55311
55466
  return [];
55312
55467
  }
55313
55468
  const keepSet = new Set(keep);
@@ -55316,12 +55471,12 @@ function pruneBundledSkills(agentDir, keep, scope) {
55316
55471
  for (const entry of scopeSet) {
55317
55472
  if (keepSet.has(entry))
55318
55473
  continue;
55319
- const entryPath = join15(skillsDir, entry);
55320
- if (!existsSync23(entryPath))
55474
+ const entryPath = join16(skillsDir, entry);
55475
+ if (!existsSync24(entryPath))
55321
55476
  continue;
55322
55477
  let isDir = false;
55323
55478
  try {
55324
- isDir = statSync14(entryPath).isDirectory();
55479
+ isDir = statSync15(entryPath).isDirectory();
55325
55480
  } catch {
55326
55481
  continue;
55327
55482
  }
@@ -55356,7 +55511,7 @@ init_vault();
55356
55511
  init_lifecycle();
55357
55512
  import { resolve as resolve19 } from "node:path";
55358
55513
  import {
55359
- existsSync as existsSync24,
55514
+ existsSync as existsSync25,
55360
55515
  mkdtempSync as mkdtempSync3,
55361
55516
  rmSync as rmSync8,
55362
55517
  cpSync
@@ -55388,7 +55543,7 @@ function defaultDeps() {
55388
55543
  },
55389
55544
  copyDir: (src, dst) => cpSync(src, dst, { recursive: true }),
55390
55545
  removeDir: (p) => rmSync8(p, { recursive: true, force: true }),
55391
- existsSync: existsSync24,
55546
+ existsSync: existsSync25,
55392
55547
  readFileSync: (p, enc) => readFileSync20(p, enc)
55393
55548
  };
55394
55549
  }
@@ -55805,11 +55960,11 @@ function checkQuarantineRefusal(agentsDir, name) {
55805
55960
  function preflightCheck(name, agentDir, _usesDevChannels) {
55806
55961
  const errors2 = [];
55807
55962
  const startSh = resolve21(agentDir, "start.sh");
55808
- if (!existsSync26(startSh)) {
55963
+ if (!existsSync27(startSh)) {
55809
55964
  errors2.push(`start.sh not found at ${startSh}`);
55810
55965
  }
55811
55966
  const envPath = resolve21(agentDir, "telegram", ".env");
55812
- if (existsSync26(envPath)) {
55967
+ if (existsSync27(envPath)) {
55813
55968
  const envContent = readFileSync22(envPath, "utf-8");
55814
55969
  if (!envContent.includes("TELEGRAM_BOT_TOKEN=") || envContent.includes("# Set your bot token")) {
55815
55970
  errors2.push(`telegram/.env is missing TELEGRAM_BOT_TOKEN. ` + `Set it or run: switchroom setup`);
@@ -55817,7 +55972,7 @@ function preflightCheck(name, agentDir, _usesDevChannels) {
55817
55972
  } else {
55818
55973
  errors2.push(`telegram/.env not found at ${envPath}`);
55819
55974
  }
55820
- if (!existsSync26(resolve21(agentDir, ".claude", "settings.json"))) {
55975
+ if (!existsSync27(resolve21(agentDir, ".claude", "settings.json"))) {
55821
55976
  errors2.push(`.claude/settings.json not found. Run: switchroom agent reconcile ${name}`);
55822
55977
  }
55823
55978
  return errors2;
@@ -55894,7 +56049,7 @@ function synthesizeTopicName2(name) {
55894
56049
  return name.split(/[-_]+/).filter((s) => s.length > 0).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join(" ");
55895
56050
  }
55896
56051
  function writeAgentEntryToConfig(configPath, name, profile) {
55897
- if (!existsSync26(configPath)) {
56052
+ if (!existsSync27(configPath)) {
55898
56053
  throw new Error(`switchroom.yaml not found at ${configPath}`);
55899
56054
  }
55900
56055
  const raw = readFileSync22(configPath, "utf-8");
@@ -55925,7 +56080,7 @@ function updateAgentExtendsInConfig(configPath, name, profile) {
55925
56080
  writeFileSync13(configPath, doc.toString(), "utf-8");
55926
56081
  }
55927
56082
  function removeAgentFromConfig(configPath, name) {
55928
- if (!existsSync26(configPath))
56083
+ if (!existsSync27(configPath))
55929
56084
  return;
55930
56085
  const raw = readFileSync22(configPath, "utf-8");
55931
56086
  const doc = import_yaml5.default.parseDocument(raw);
@@ -55939,7 +56094,8 @@ async function reconcileAndRestartAgent(name, config, agentsDir, configPath, opt
55939
56094
  reconcileAgent,
55940
56095
  restartAgent,
55941
56096
  gracefulRestartAgent,
55942
- applyCronChangesHot
56097
+ applyCronChangesHot,
56098
+ writeComposeFile
55943
56099
  }) {
55944
56100
  const log = opts.silent ? () => {} : (msg) => console.log(msg);
55945
56101
  const agentConfig = config.agents[name];
@@ -55972,7 +56128,7 @@ async function reconcileAndRestartAgent(name, config, agentsDir, configPath, opt
55972
56128
  }
55973
56129
  if (!opts.force) {
55974
56130
  const envPath = resolve21(agentsDir, name, "telegram", ".env");
55975
- if (existsSync26(envPath)) {
56131
+ if (existsSync27(envPath)) {
55976
56132
  const envContent = readFileSync22(envPath, "utf-8");
55977
56133
  const match = envContent.match(/^TELEGRAM_BOT_TOKEN=(.+)$/m);
55978
56134
  if (match) {
@@ -55988,6 +56144,20 @@ async function reconcileAndRestartAgent(name, config, agentsDir, configPath, opt
55988
56144
  }
55989
56145
  }
55990
56146
  }
56147
+ try {
56148
+ const r = await deps.writeComposeFile({
56149
+ config,
56150
+ composePath: opts.composePath ?? composeFilePath(),
56151
+ switchroomConfigPath: configPath
56152
+ });
56153
+ if (r.changed) {
56154
+ const tagNote = r.previousImageTag && r.previousImageTag !== r.imageTag ? ` (image ${r.previousImageTag} \u2192 ${r.imageTag})` : ` (image ${r.imageTag})`;
56155
+ log(source_default.green(` ${name}: compose regenerated${tagNote}`));
56156
+ }
56157
+ } catch (err) {
56158
+ const msg = err instanceof Error ? err.message : String(err);
56159
+ log(source_default.yellow(` ${name}: could not regenerate compose (${msg}) \u2014 image/pin changes may not apply; run \`switchroom apply\``));
56160
+ }
55991
56161
  if (opts.graceful) {
55992
56162
  try {
55993
56163
  const r = await deps.gracefulRestartAgent(name);
@@ -56022,7 +56192,7 @@ function registerAgentCommand(program3) {
56022
56192
  }
56023
56193
  return;
56024
56194
  }
56025
- const logsDir = join17(homedir6(), ".switchroom", "logs");
56195
+ const logsDir = join18(homedir7(), ".switchroom", "logs");
56026
56196
  const schedulerStates = Object.fromEntries(agentNames.map((n) => [n, getSchedulerState(n, logsDir)]));
56027
56197
  if (opts.json) {
56028
56198
  const data = agentNames.map((name) => {
@@ -56453,7 +56623,7 @@ Scaffolding agent: ${name}
56453
56623
  });
56454
56624
  const settingsPath = resolve21(agentsDir, n, ".claude", "settings.json");
56455
56625
  let actual = {};
56456
- if (existsSync26(settingsPath)) {
56626
+ if (existsSync27(settingsPath)) {
56457
56627
  try {
56458
56628
  const raw = JSON.parse(readFileSync22(settingsPath, "utf-8"));
56459
56629
  actual = raw.hooks ?? {};
@@ -56593,7 +56763,7 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
56593
56763
  }));
56594
56764
  agent.command("grant <name> <tool>").description("Add a tool name (or 'all') to an agent's tools.allow in switchroom.yaml, then reconcile").option("--no-restart", "Skip restarting the agent after granting").action(withConfigError(async (name, tool, opts) => {
56595
56765
  const configPath = getConfigPath(program3);
56596
- if (!existsSync26(configPath)) {
56766
+ if (!existsSync27(configPath)) {
56597
56767
  console.error(source_default.red(`switchroom.yaml not found at ${configPath}`));
56598
56768
  process.exit(1);
56599
56769
  }
@@ -56642,7 +56812,7 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
56642
56812
  }));
56643
56813
  agent.command("dangerous <name>").description("Enable full tool access for an agent (sets tools.allow: [all] in switchroom.yaml). Reconciles + restarts.").option("--off", "Disable: clear tools.allow").option("--no-restart", "Skip restarting the agent").action(withConfigError(async (name, opts) => {
56644
56814
  const configPath = getConfigPath(program3);
56645
- if (!existsSync26(configPath)) {
56815
+ if (!existsSync27(configPath)) {
56646
56816
  console.error(source_default.red(`switchroom.yaml not found at ${configPath}`));
56647
56817
  process.exit(1);
56648
56818
  }
@@ -56697,7 +56867,7 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
56697
56867
  const config = getConfig(program3);
56698
56868
  const agentsDir = resolveAgentsDir(config);
56699
56869
  const settingsPath = resolve21(agentsDir, name, ".claude", "settings.json");
56700
- if (!existsSync26(settingsPath)) {
56870
+ if (!existsSync27(settingsPath)) {
56701
56871
  console.error(source_default.red(`Agent "${name}" not found at ${settingsPath}`));
56702
56872
  process.exit(1);
56703
56873
  }
@@ -56756,7 +56926,7 @@ Permissions for ${name}
56756
56926
  }
56757
56927
  }
56758
56928
  }
56759
- if (existsSync26(agentDir)) {
56929
+ if (existsSync27(agentDir)) {
56760
56930
  rmSync9(agentDir, { recursive: true, force: true });
56761
56931
  console.log(source_default.green(` Removed directory: ${agentDir}`));
56762
56932
  } else {
@@ -56960,7 +57130,7 @@ switchroom agent add: ${name}
56960
57130
  } catch {}
56961
57131
  const agentsDirRollback = resolveAgentsDir(cfg);
56962
57132
  const agentDirRollback = resolve21(agentsDirRollback, name);
56963
- if (existsSync26(agentDirRollback)) {
57133
+ if (existsSync27(agentDirRollback)) {
56964
57134
  rmSync9(agentDirRollback, { recursive: true, force: true });
56965
57135
  console.log(source_default.gray(` Rolled back: removed ${agentDirRollback}`));
56966
57136
  }
@@ -57059,8 +57229,8 @@ init_source();
57059
57229
  init_lifecycle();
57060
57230
  import { execFile as execFile2 } from "node:child_process";
57061
57231
  import { promisify as promisify2 } from "node:util";
57062
- import { homedir as homedir8 } from "node:os";
57063
- import { join as join19 } from "node:path";
57232
+ import { homedir as homedir9 } from "node:os";
57233
+ import { join as join20 } from "node:path";
57064
57234
  init_helpers();
57065
57235
  init_broker_call();
57066
57236
  var execFileP = promisify2(execFile2);
@@ -57132,7 +57302,7 @@ function registerStatusCommand(program3) {
57132
57302
  const config = getConfig(program3);
57133
57303
  const agentNames = Object.keys(config.agents ?? {}).sort();
57134
57304
  const statuses = getAllAgentStatuses(config);
57135
- const logsDir = join19(homedir8(), ".switchroom", "logs");
57305
+ const logsDir = join20(homedir9(), ".switchroom", "logs");
57136
57306
  const schedulerStates = Object.fromEntries(agentNames.map((n) => [n, getSchedulerState(n, logsDir)]));
57137
57307
  const accountsP = fetchAccounts();
57138
57308
  const mcpEnabled = opts.mcp !== false;
@@ -57541,8 +57711,8 @@ init_account_store();
57541
57711
  init_loader();
57542
57712
  init_manager();
57543
57713
  init_helpers();
57544
- import { existsSync as existsSync31, readFileSync as readFileSync27 } from "node:fs";
57545
- import { join as join23, resolve as resolve24 } from "node:path";
57714
+ import { existsSync as existsSync32, readFileSync as readFileSync27 } from "node:fs";
57715
+ import { join as join24, resolve as resolve24 } from "node:path";
57546
57716
 
57547
57717
  // src/cli/auth-google.ts
57548
57718
  init_source();
@@ -57759,8 +57929,8 @@ function registerConnect(googleParent, program3) {
57759
57929
  }
57760
57930
  let mode = 420;
57761
57931
  try {
57762
- const { statSync: statSync16 } = await import("node:fs");
57763
- mode = statSync16(configPath).mode & 511;
57932
+ const { statSync: statSync17 } = await import("node:fs");
57933
+ mode = statSync17(configPath).mode & 511;
57764
57934
  } catch {}
57765
57935
  atomicWriteFileSync3(configPath, patched, mode);
57766
57936
  try {
@@ -59058,7 +59228,7 @@ function registerAuthScheduleSubcommands(_program, authParent) {
59058
59228
  // src/cli/auth.ts
59059
59229
  init_auth_active_yaml();
59060
59230
  init_atomic();
59061
- import { statSync as statSync16 } from "node:fs";
59231
+ import { statSync as statSync17 } from "node:fs";
59062
59232
  var SEVERITY_RANK = {
59063
59233
  ok: 0,
59064
59234
  warn: 1,
@@ -59067,10 +59237,10 @@ var SEVERITY_RANK = {
59067
59237
  };
59068
59238
  function diagnoseAuthState(claudeConfigDir) {
59069
59239
  const findings = [];
59070
- const credsPath = join23(claudeConfigDir, ".credentials.json");
59071
- const oauthTokenPath2 = join23(claudeConfigDir, ".oauth-token");
59072
- const hasCreds = existsSync31(credsPath);
59073
- const hasOauthToken = existsSync31(oauthTokenPath2);
59240
+ const credsPath = join24(claudeConfigDir, ".credentials.json");
59241
+ const oauthTokenPath2 = join24(claudeConfigDir, ".oauth-token");
59242
+ const hasCreds = existsSync32(credsPath);
59243
+ const hasOauthToken = existsSync32(oauthTokenPath2);
59074
59244
  if (!hasCreds && !hasOauthToken) {
59075
59245
  findings.push({
59076
59246
  code: "credentials_missing",
@@ -59241,8 +59411,8 @@ function loadCredentialsFromAgent(agentName) {
59241
59411
  const config = getConfigSafe();
59242
59412
  const agentsDir = resolveAgentsDir(config);
59243
59413
  const agentDir = resolve24(agentsDir, agentName);
59244
- const credsPath = join23(agentDir, ".claude", ".credentials.json");
59245
- if (!existsSync31(credsPath)) {
59414
+ const credsPath = join24(agentDir, ".claude", ".credentials.json");
59415
+ if (!existsSync32(credsPath)) {
59246
59416
  console.error(source_default.red(` Agent "${agentName}" has no .claude/.credentials.json \u2014 log it in first.`));
59247
59417
  process.exit(1);
59248
59418
  }
@@ -59260,7 +59430,7 @@ function loadCredentialsFromAgent(agentName) {
59260
59430
  return parsed;
59261
59431
  }
59262
59432
  function loadCredentialsFromFile(path) {
59263
- if (!existsSync31(path)) {
59433
+ if (!existsSync32(path)) {
59264
59434
  console.error(source_default.red(` No file at ${path}`));
59265
59435
  process.exit(1);
59266
59436
  }
@@ -59299,12 +59469,12 @@ function loadCredentialsFromGlobalAccount(label) {
59299
59469
  };
59300
59470
  }
59301
59471
  async function loadCredentialsViaClaude(label) {
59302
- const [{ runViaClaude: runViaClaude2 }, { homedir: homedir11 }, { default: readline }] = await Promise.all([
59472
+ const [{ runViaClaude: runViaClaude2 }, { homedir: homedir12 }, { default: readline }] = await Promise.all([
59303
59473
  Promise.resolve().then(() => (init_via_claude(), exports_via_claude)),
59304
59474
  import("node:os"),
59305
59475
  import("node:readline")
59306
59476
  ]);
59307
- const configDir = join23(homedir11(), ".switchroom", "accounts", label);
59477
+ const configDir = join24(homedir12(), ".switchroom", "accounts", label);
59308
59478
  const result = await runViaClaude2({
59309
59479
  configDir,
59310
59480
  promptForCode: async (_url) => {
@@ -59346,7 +59516,7 @@ function registerAuthCommand(program3) {
59346
59516
  await withConfigError(async () => {
59347
59517
  const config = getConfig(program3);
59348
59518
  const agentsDir = resolveAgentsDir(config);
59349
- configDir = join23(agentsDir, agent, ".claude");
59519
+ configDir = join24(agentsDir, agent, ".claude");
59350
59520
  })();
59351
59521
  }
59352
59522
  const diag = diagnoseAuthState(configDir);
@@ -59405,7 +59575,7 @@ function registerAuthCommand(program3) {
59405
59575
  if (after !== before) {
59406
59576
  let mode = 420;
59407
59577
  try {
59408
- mode = statSync16(yamlPath).mode & 511;
59578
+ mode = statSync17(yamlPath).mode & 511;
59409
59579
  } catch {}
59410
59580
  atomicWriteFileSync2(yamlPath, after, mode);
59411
59581
  if (!quiet) {
@@ -59505,7 +59675,7 @@ function registerAuthCommand(program3) {
59505
59675
  }));
59506
59676
  auth.command("reauth <agent>").description("Start/resume an OAuth re-auth session for an agent; prints the login URL").option("--slot <label>", "Target a specific account slot/label instead of the agent's active one").option("--force", "Kill any existing session and force a fresh login (use to switch accounts)").action(withConfigError(async (agent, opts) => {
59507
59677
  const config = getConfig(program3);
59508
- const agentDir = join23(resolveAgentsDir(config), agent);
59678
+ const agentDir = join24(resolveAgentsDir(config), agent);
59509
59679
  const r = startAuthSession(agent, agentDir, {
59510
59680
  force: opts.force,
59511
59681
  slot: opts.slot
@@ -59518,7 +59688,7 @@ function registerAuthCommand(program3) {
59518
59688
  }));
59519
59689
  auth.command("code <agent> <code>").description("Submit the browser OAuth code to complete a pending `auth reauth`").option("--slot <label>", "Target a specific account slot/label").option("--json", "Emit the structured AuthCodeResult as JSON (consumed by the Telegram gateway)").action(withConfigError(async (agent, code, opts) => {
59520
59690
  const config = getConfig(program3);
59521
- const agentDir = join23(resolveAgentsDir(config), agent);
59691
+ const agentDir = join24(resolveAgentsDir(config), agent);
59522
59692
  const r = submitAuthCode(agent, agentDir, code, opts.slot);
59523
59693
  if (opts.json) {
59524
59694
  console.log(JSON.stringify({
@@ -59535,7 +59705,7 @@ function registerAuthCommand(program3) {
59535
59705
  }));
59536
59706
  auth.command("cancel <agent>").description("Cancel a pending `auth reauth` session for an agent").option("--slot <label>", "Target a specific account slot/label").action(withConfigError(async (agent, opts) => {
59537
59707
  const config = getConfig(program3);
59538
- const agentDir = join23(resolveAgentsDir(config), agent);
59708
+ const agentDir = join24(resolveAgentsDir(config), agent);
59539
59709
  const r = cancelAuthSession(agent, agentDir, opts.slot);
59540
59710
  for (const line of r.instructions)
59541
59711
  console.log(line);
@@ -59555,10 +59725,10 @@ init_source();
59555
59725
  init_loader();
59556
59726
  init_vault();
59557
59727
  init_hindsight();
59558
- import { readFileSync as readFileSync28, writeFileSync as writeFileSync17, copyFileSync as copyFileSync6, existsSync as existsSync32, readdirSync as readdirSync15, statSync as statSync17 } from "node:fs";
59728
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync17, copyFileSync as copyFileSync6, existsSync as existsSync33, readdirSync as readdirSync16, statSync as statSync18 } from "node:fs";
59559
59729
  import { execFileSync as execFileSync15 } from "node:child_process";
59560
- import { join as join24 } from "node:path";
59561
- import { homedir as homedir11 } from "node:os";
59730
+ import { join as join25 } from "node:path";
59731
+ import { homedir as homedir12 } from "node:os";
59562
59732
  function getVaultPath2(configPath) {
59563
59733
  try {
59564
59734
  const config = loadConfig(configPath);
@@ -59573,22 +59743,22 @@ function maskToken(s) {
59573
59743
  return "***";
59574
59744
  }
59575
59745
  function findClaudeTranscripts() {
59576
- const root = join24(homedir11(), ".claude", "projects");
59577
- if (!existsSync32(root))
59746
+ const root = join25(homedir12(), ".claude", "projects");
59747
+ if (!existsSync33(root))
59578
59748
  return [];
59579
59749
  const out = [];
59580
59750
  const walk = (dir) => {
59581
59751
  let entries;
59582
59752
  try {
59583
- entries = readdirSync15(dir);
59753
+ entries = readdirSync16(dir);
59584
59754
  } catch {
59585
59755
  return;
59586
59756
  }
59587
59757
  for (const e of entries) {
59588
- const p = join24(dir, e);
59758
+ const p = join25(dir, e);
59589
59759
  let st;
59590
59760
  try {
59591
- st = statSync17(p);
59761
+ st = statSync18(p);
59592
59762
  } catch {
59593
59763
  continue;
59594
59764
  }
@@ -59604,11 +59774,11 @@ function findClaudeTranscripts() {
59604
59774
  }
59605
59775
  function findTelegramHistoryDb() {
59606
59776
  const candidates = [
59607
- process.env.TELEGRAM_STATE_DIR ? join24(process.env.TELEGRAM_STATE_DIR, "history.db") : null,
59608
- join24(homedir11(), ".claude", "channels", "telegram", "history.db")
59777
+ process.env.TELEGRAM_STATE_DIR ? join25(process.env.TELEGRAM_STATE_DIR, "history.db") : null,
59778
+ join25(homedir12(), ".claude", "channels", "telegram", "history.db")
59609
59779
  ].filter(Boolean);
59610
59780
  for (const c of candidates) {
59611
- if (existsSync32(c))
59781
+ if (existsSync33(c))
59612
59782
  return c;
59613
59783
  }
59614
59784
  return null;
@@ -59964,15 +60134,15 @@ function suggestVaultKeys(requested, available, max = 3) {
59964
60134
  init_loader();
59965
60135
  init_loader();
59966
60136
  init_client();
59967
- import { readFileSync as readFileSync33, existsSync as existsSync36, unlinkSync as unlinkSync9 } from "node:fs";
60137
+ import { readFileSync as readFileSync33, existsSync as existsSync37, unlinkSync as unlinkSync9 } from "node:fs";
59968
60138
  import { spawn as spawn4 } from "node:child_process";
59969
60139
 
59970
60140
  // src/vault/broker/server.ts
59971
60141
  init_compose();
59972
60142
  init_vault();
59973
60143
  import * as net3 from "node:net";
59974
- import { mkdirSync as mkdirSync22, chmodSync as chmodSync7, chownSync as chownSync2, existsSync as existsSync35, readFileSync as readFileSync31, readdirSync as readdirSync16, statSync as statSync19, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19, renameSync as renameSync10 } from "node:fs";
59975
- import { dirname as dirname6, resolve as resolve26, basename as basename4 } from "node:path";
60144
+ import { mkdirSync as mkdirSync22, chmodSync as chmodSync7, chownSync as chownSync4, existsSync as existsSync36, readFileSync as readFileSync31, readdirSync as readdirSync17, statSync as statSync20, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19, renameSync as renameSync10 } from "node:fs";
60145
+ import { dirname as dirname7, resolve as resolve26, basename as basename4 } from "node:path";
59976
60146
  import * as os4 from "node:os";
59977
60147
  import * as path3 from "node:path";
59978
60148
 
@@ -59981,26 +60151,26 @@ init_vault();
59981
60151
  import {
59982
60152
  copyFileSync as copyFileSync7,
59983
60153
  chmodSync as chmodSync4,
59984
- existsSync as existsSync33,
60154
+ existsSync as existsSync34,
59985
60155
  fsyncSync as fsyncSync4,
59986
- lstatSync as lstatSync4,
60156
+ lstatSync as lstatSync5,
59987
60157
  mkdirSync as mkdirSync19,
59988
60158
  openSync as openSync6,
59989
60159
  closeSync as closeSync6,
59990
60160
  readFileSync as readFileSync29,
59991
60161
  renameSync as renameSync9,
59992
- statSync as statSync18,
60162
+ statSync as statSync19,
59993
60163
  symlinkSync as symlinkSync3,
59994
60164
  unlinkSync as unlinkSync7
59995
60165
  } from "node:fs";
59996
60166
  import { createHash as createHash5 } from "node:crypto";
59997
- import { basename as basename3, dirname as dirname3, join as join25 } from "node:path";
60167
+ import { basename as basename3, dirname as dirname4, join as join26 } from "node:path";
59998
60168
  function vaultLayoutPaths(home2) {
59999
- const switchroomRoot = join25(home2, ".switchroom");
60169
+ const switchroomRoot = join26(home2, ".switchroom");
60000
60170
  return {
60001
- oldPath: join25(switchroomRoot, "vault.enc"),
60002
- newPath: join25(switchroomRoot, "vault", "vault.enc"),
60003
- parent: join25(switchroomRoot, "vault"),
60171
+ oldPath: join26(switchroomRoot, "vault.enc"),
60172
+ newPath: join26(switchroomRoot, "vault", "vault.enc"),
60173
+ parent: join26(switchroomRoot, "vault"),
60004
60174
  switchroomRoot
60005
60175
  };
60006
60176
  }
@@ -60020,11 +60190,11 @@ function migrateVaultLayout(home2, opts = {}) {
60020
60190
  }
60021
60191
  function runMigration(home2, opts) {
60022
60192
  const { oldPath, newPath, parent, switchroomRoot } = vaultLayoutPaths(home2);
60023
- const lockTarget = existsSync33(newPath) ? newPath : existsSync33(oldPath) ? oldPath : null;
60193
+ const lockTarget = existsSync34(newPath) ? newPath : existsSync34(oldPath) ? oldPath : null;
60024
60194
  const release = !opts.dryRun && lockTarget !== null ? acquireVaultLock(lockTarget) : null;
60025
60195
  try {
60026
60196
  const oldStat = lstatSyncOrNull(oldPath);
60027
- const newExists = existsSync33(newPath);
60197
+ const newExists = existsSync34(newPath);
60028
60198
  if (oldStat === null && !newExists) {
60029
60199
  return { kind: "no-vault" };
60030
60200
  }
@@ -60041,8 +60211,8 @@ function runMigration(home2, opts) {
60041
60211
  fsyncDir(switchroomRoot);
60042
60212
  return { kind: "completed-partial" };
60043
60213
  }
60044
- const oldRealStat = statSync18(oldPath);
60045
- const newRealStat = statSync18(newPath);
60214
+ const oldRealStat = statSync19(oldPath);
60215
+ const newRealStat = statSync19(newPath);
60046
60216
  return {
60047
60217
  kind: "divergent",
60048
60218
  details: {
@@ -60137,7 +60307,7 @@ your fleet works after \`switchroom apply\`, then delete it.
60137
60307
  }
60138
60308
  function lstatSyncOrNull(path) {
60139
60309
  try {
60140
- return lstatSync4(path);
60310
+ return lstatSync5(path);
60141
60311
  } catch {
60142
60312
  return null;
60143
60313
  }
@@ -60147,8 +60317,8 @@ function sha256File(path) {
60147
60317
  return createHash5("sha256").update(data).digest("hex");
60148
60318
  }
60149
60319
  function atomicReplaceWithSymlink(target, linkTarget) {
60150
- const tmp = join25(dirname3(target), `.${basename3(target)}.symlink-tmp`);
60151
- if (existsSync33(tmp)) {
60320
+ const tmp = join26(dirname4(target), `.${basename3(target)}.symlink-tmp`);
60321
+ if (existsSync34(tmp)) {
60152
60322
  try {
60153
60323
  unlinkSync7(tmp);
60154
60324
  } catch {}
@@ -60178,8 +60348,8 @@ init_loader();
60178
60348
 
60179
60349
  // src/vault/auto-unlock.ts
60180
60350
  import { createHmac, randomBytes as randomBytes6, createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2 } from "node:crypto";
60181
- import { chmodSync as chmodSync5, existsSync as existsSync34, mkdirSync as mkdirSync20, readFileSync as readFileSync30, writeFileSync as writeFileSync18 } from "node:fs";
60182
- import { dirname as dirname4 } from "node:path";
60351
+ import { chmodSync as chmodSync5, existsSync as existsSync35, mkdirSync as mkdirSync20, readFileSync as readFileSync30, writeFileSync as writeFileSync18 } from "node:fs";
60352
+ import { dirname as dirname5 } from "node:path";
60183
60353
  var FORMAT_VERSION = 1;
60184
60354
  var SALT_LEN = 16;
60185
60355
  var NONCE_LEN = 12;
@@ -60268,12 +60438,12 @@ function decryptAutoUnlock(blob, machineId) {
60268
60438
  }
60269
60439
  function writeAutoUnlockFile(passphrase, filePath) {
60270
60440
  const blob = encryptAutoUnlock(passphrase);
60271
- mkdirSync20(dirname4(filePath), { recursive: true, mode: 448 });
60441
+ mkdirSync20(dirname5(filePath), { recursive: true, mode: 448 });
60272
60442
  writeFileSync18(filePath, blob, { mode: 384 });
60273
60443
  chmodSync5(filePath, 384);
60274
60444
  }
60275
60445
  function readAutoUnlockFile(filePath) {
60276
- if (!existsSync34(filePath)) {
60446
+ if (!existsSync35(filePath)) {
60277
60447
  throw new AutoUnlockDecryptError("io");
60278
60448
  }
60279
60449
  let blob;
@@ -60299,8 +60469,8 @@ import * as path from "node:path";
60299
60469
 
60300
60470
  // src/vault/broker/test-isolation-guard.ts
60301
60471
  import { mkdtempSync as mkdtempSync4 } from "node:fs";
60302
- import { homedir as homedir12, tmpdir as tmpdir3 } from "node:os";
60303
- import { join as join26, resolve as resolve25, sep } from "node:path";
60472
+ import { homedir as homedir13, tmpdir as tmpdir3 } from "node:os";
60473
+ import { join as join27, resolve as resolve25, sep } from "node:path";
60304
60474
  function isTestRuntime() {
60305
60475
  return process.env.VITEST !== undefined;
60306
60476
  }
@@ -60308,7 +60478,7 @@ function escapeHatchSet() {
60308
60478
  return process.env.SWITCHROOM_ALLOW_PROD_VAULT_IN_TEST === "1";
60309
60479
  }
60310
60480
  function realSwitchroomHome() {
60311
- return resolve25(homedir12(), ".switchroom");
60481
+ return resolve25(homedir13(), ".switchroom");
60312
60482
  }
60313
60483
  function isUnderRealSwitchroomHome(p) {
60314
60484
  const home2 = realSwitchroomHome();
@@ -60321,7 +60491,7 @@ function safeVaultPath(requestedPath) {
60321
60491
  return requestedPath;
60322
60492
  if (!isUnderRealSwitchroomHome(requestedPath))
60323
60493
  return requestedPath;
60324
- const redirected = join26(mkdtempSync4(join26(tmpdir3(), "sw-test-vault-")), "vault.enc");
60494
+ const redirected = join27(mkdtempSync4(join27(tmpdir3(), "sw-test-vault-")), "vault.enc");
60325
60495
  if (!warnedVault) {
60326
60496
  warnedVault = true;
60327
60497
  process.stderr.write(`[test-isolation guard] vault path redirected away from the ` + `production tree to an isolated tmpdir \u2014 a vault/broker test ` + `resolved its vault path inside ~/.switchroom. See CLAUDE.md ` + `"Vault & shared-state test discipline".
@@ -60337,7 +60507,7 @@ function safeAuditLogPath(requestedPath) {
60337
60507
  if (!isUnderRealSwitchroomHome(requestedPath))
60338
60508
  return requestedPath;
60339
60509
  if (!cachedTmpAuditLog) {
60340
- cachedTmpAuditLog = join26(mkdtempSync4(join26(tmpdir3(), "sw-test-audit-")), "vault-audit.log");
60510
+ cachedTmpAuditLog = join27(mkdtempSync4(join27(tmpdir3(), "sw-test-audit-")), "vault-audit.log");
60341
60511
  }
60342
60512
  if (!warnedAudit) {
60343
60513
  warnedAudit = true;
@@ -62700,13 +62870,13 @@ class VaultBroker {
62700
62870
  this.passphrase = this.testOpts._testPassphrase;
62701
62871
  }
62702
62872
  process.umask(63);
62703
- const parentDir = dirname6(this.socketPath);
62873
+ const parentDir = dirname7(this.socketPath);
62704
62874
  mkdirSync22(parentDir, { recursive: true, mode: 448 });
62705
62875
  try {
62706
62876
  chmodSync7(parentDir, 448);
62707
62877
  } catch {}
62708
62878
  for (const p of [this.socketPath, this.unlockSocketPath]) {
62709
- if (existsSync35(p)) {
62879
+ if (existsSync36(p)) {
62710
62880
  try {
62711
62881
  unlinkSync8(p);
62712
62882
  } catch {}
@@ -62739,7 +62909,7 @@ class VaultBroker {
62739
62909
  try {
62740
62910
  if (ready) {
62741
62911
  writeFileSync19(p, "", { mode: 384 });
62742
- } else if (existsSync35(p)) {
62912
+ } else if (existsSync36(p)) {
62743
62913
  unlinkSync8(p);
62744
62914
  }
62745
62915
  } catch {}
@@ -62772,7 +62942,7 @@ class VaultBroker {
62772
62942
  try {
62773
62943
  entry.server.close();
62774
62944
  } catch {}
62775
- if (existsSync35(sockPath)) {
62945
+ if (existsSync36(sockPath)) {
62776
62946
  try {
62777
62947
  unlinkSync8(sockPath);
62778
62948
  } catch {}
@@ -62780,7 +62950,7 @@ class VaultBroker {
62780
62950
  }
62781
62951
  this.agentServers.clear();
62782
62952
  for (const p of [this.socketPath, this.unlockSocketPath]) {
62783
- if (p && existsSync35(p)) {
62953
+ if (p && existsSync36(p)) {
62784
62954
  try {
62785
62955
  unlinkSync8(p);
62786
62956
  } catch {}
@@ -62788,7 +62958,7 @@ class VaultBroker {
62788
62958
  }
62789
62959
  try {
62790
62960
  const pidPath = resolvePath(PID_FILE_DEFAULT);
62791
- if (existsSync35(pidPath))
62961
+ if (existsSync36(pidPath))
62792
62962
  unlinkSync8(pidPath);
62793
62963
  } catch {}
62794
62964
  }
@@ -62811,16 +62981,16 @@ class VaultBroker {
62811
62981
  return new Promise((resolveP, rejectP) => {
62812
62982
  if (abs.endsWith("/sock")) {
62813
62983
  const dir = abs.slice(0, -"/sock".length);
62814
- if (existsSync35(dir)) {
62984
+ if (existsSync36(dir)) {
62815
62985
  try {
62816
- chownSync2(dir, 0, 0);
62986
+ chownSync4(dir, 0, 0);
62817
62987
  } catch {}
62818
62988
  try {
62819
62989
  chmodSync7(dir, 448);
62820
62990
  } catch {}
62821
62991
  }
62822
62992
  }
62823
- if (existsSync35(abs)) {
62993
+ if (existsSync36(abs)) {
62824
62994
  try {
62825
62995
  unlinkSync8(abs);
62826
62996
  } catch (err) {
@@ -62841,18 +63011,18 @@ class VaultBroker {
62841
63011
  try {
62842
63012
  agentUid = allocateAgentUid(agentName);
62843
63013
  try {
62844
- chownSync2(abs, agentUid, agentUid);
63014
+ chownSync4(abs, agentUid, agentUid);
62845
63015
  } catch {}
62846
63016
  if (abs.endsWith("/sock")) {
62847
63017
  const dir = abs.slice(0, -"/sock".length);
62848
63018
  try {
62849
- chownSync2(dir, agentUid, agentUid);
63019
+ chownSync4(dir, agentUid, agentUid);
62850
63020
  } catch {}
62851
63021
  }
62852
63022
  } catch {}
62853
63023
  this.agentServers.set(abs, { server, agentName });
62854
63024
  const unlockAbs = unlockSocketFor(abs);
62855
- if (existsSync35(unlockAbs)) {
63025
+ if (existsSync36(unlockAbs)) {
62856
63026
  try {
62857
63027
  unlinkSync8(unlockAbs);
62858
63028
  } catch {}
@@ -62873,7 +63043,7 @@ class VaultBroker {
62873
63043
  } catch {}
62874
63044
  if (agentUid !== null) {
62875
63045
  try {
62876
- chownSync2(unlockAbs, agentUid, agentUid);
63046
+ chownSync4(unlockAbs, agentUid, agentUid);
62877
63047
  } catch {}
62878
63048
  }
62879
63049
  this.agentServers.set(unlockAbs, { server: unlockServer, agentName });
@@ -62907,8 +63077,8 @@ class VaultBroker {
62907
63077
  if (!Number.isFinite(uid) || uid <= 0)
62908
63078
  return;
62909
63079
  try {
62910
- if (existsSync35(this.vaultPath))
62911
- chownSync2(this.vaultPath, uid, uid);
63080
+ if (existsSync36(this.vaultPath))
63081
+ chownSync4(this.vaultPath, uid, uid);
62912
63082
  } catch {}
62913
63083
  }
62914
63084
  bindOperatorListener(socketPath, operatorUid) {
@@ -62920,9 +63090,9 @@ class VaultBroker {
62920
63090
  const unlockAbs = unlockSocketFor(abs);
62921
63091
  if (abs.endsWith("/sock")) {
62922
63092
  const dir = abs.slice(0, -"/sock".length);
62923
- if (existsSync35(dir)) {
63093
+ if (existsSync36(dir)) {
62924
63094
  try {
62925
- chownSync2(dir, 0, 0);
63095
+ chownSync4(dir, 0, 0);
62926
63096
  } catch {}
62927
63097
  try {
62928
63098
  chmodSync7(dir, 448);
@@ -62930,7 +63100,7 @@ class VaultBroker {
62930
63100
  }
62931
63101
  }
62932
63102
  for (const p of [abs, unlockAbs]) {
62933
- if (existsSync35(p)) {
63103
+ if (existsSync36(p)) {
62934
63104
  try {
62935
63105
  unlinkSync8(p);
62936
63106
  } catch {}
@@ -62946,7 +63116,7 @@ class VaultBroker {
62946
63116
  chmodSync7(abs, 384);
62947
63117
  } catch {}
62948
63118
  try {
62949
- chownSync2(abs, operatorUid, operatorUid);
63119
+ chownSync4(abs, operatorUid, operatorUid);
62950
63120
  } catch {}
62951
63121
  const unlockServer = net3.createServer((sock) => {
62952
63122
  this._handleUnlockConnection(sock, true);
@@ -62957,12 +63127,12 @@ class VaultBroker {
62957
63127
  chmodSync7(unlockAbs, 384);
62958
63128
  } catch {}
62959
63129
  try {
62960
- chownSync2(unlockAbs, operatorUid, operatorUid);
63130
+ chownSync4(unlockAbs, operatorUid, operatorUid);
62961
63131
  } catch {}
62962
63132
  if (abs.endsWith("/sock")) {
62963
63133
  const dir = abs.slice(0, -"/sock".length);
62964
63134
  try {
62965
- chownSync2(dir, operatorUid, operatorUid);
63135
+ chownSync4(dir, operatorUid, operatorUid);
62966
63136
  } catch {}
62967
63137
  try {
62968
63138
  chmodSync7(dir, 448);
@@ -63797,7 +63967,7 @@ class VaultBroker {
63797
63967
  renameSync10(tmpPath, tokenPath);
63798
63968
  try {
63799
63969
  const uid = allocateAgentUid(agent);
63800
- chownSync2(tokenPath, uid, uid);
63970
+ chownSync4(tokenPath, uid, uid);
63801
63971
  } catch (chownErr) {
63802
63972
  process.stderr.write(`[vault-broker] mint_grant: token written but chown failed for agent ${agent}: ${chownErr.message} (CAP_CHOWN missing?)
63803
63973
  `);
@@ -63854,7 +64024,7 @@ class VaultBroker {
63854
64024
  const row = this.grantsDb.query("SELECT agent_slug FROM vault_grants WHERE id = ?").get(id);
63855
64025
  if (row && AgentNameSchema.safeParse(row.agent_slug).success) {
63856
64026
  const tokenPath = path3.join(os4.homedir(), ".switchroom", "agents", row.agent_slug, ".vault-token");
63857
- if (existsSync35(tokenPath)) {
64027
+ if (existsSync36(tokenPath)) {
63858
64028
  try {
63859
64029
  unlinkSync8(tokenPath);
63860
64030
  } catch {}
@@ -64092,10 +64262,10 @@ class VaultBroker {
64092
64262
  const envPath = process.env.SWITCHROOM_VAULT_BROKER_AUTO_UNLOCK_PATH;
64093
64263
  const configuredPath = (envPath && envPath.length > 0 ? envPath : undefined) ?? this.config?.vault?.broker?.autoUnlockCredentialPath ?? DEFAULT_AUTO_UNLOCK_PATH;
64094
64264
  const filePath = resolvePath(configuredPath);
64095
- if (!existsSync35(filePath))
64265
+ if (!existsSync36(filePath))
64096
64266
  return false;
64097
64267
  try {
64098
- if (statSync19(filePath).size === 0)
64268
+ if (statSync20(filePath).size === 0)
64099
64269
  return false;
64100
64270
  } catch {
64101
64271
  return false;
@@ -64173,15 +64343,15 @@ class VaultBroker {
64173
64343
  }
64174
64344
  }
64175
64345
  function detectVaultLayoutDrift(vaultPath) {
64176
- const dir = dirname6(vaultPath);
64346
+ const dir = dirname7(vaultPath);
64177
64347
  if (basename4(dir) !== "vault")
64178
64348
  return;
64179
64349
  if (basename4(vaultPath) !== "vault.enc")
64180
64350
  return;
64181
- const switchroomDir = dirname6(dir);
64351
+ const switchroomDir = dirname7(dir);
64182
64352
  if (basename4(switchroomDir) !== ".switchroom")
64183
64353
  return;
64184
- const home2 = dirname6(switchroomDir);
64354
+ const home2 = dirname7(switchroomDir);
64185
64355
  const result = inspectVaultLayout(home2);
64186
64356
  if (result.kind === "divergent") {
64187
64357
  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.`);
@@ -64207,8 +64377,8 @@ async function main() {
64207
64377
  const vaultPath = process.env.SWITCHROOM_VAULT_PATH;
64208
64378
  let perAgentTargets = [];
64209
64379
  try {
64210
- if (existsSync35(perAgentDir)) {
64211
- const entries = readdirSync16(perAgentDir, { withFileTypes: true });
64380
+ if (existsSync36(perAgentDir)) {
64381
+ const entries = readdirSync17(perAgentDir, { withFileTypes: true });
64212
64382
  const flat = [];
64213
64383
  const subdirs = [];
64214
64384
  for (const e of entries) {
@@ -64249,7 +64419,7 @@ async function main() {
64249
64419
  }
64250
64420
  const operatorUidStr = process.env.SWITCHROOM_BROKER_OPERATOR_UID;
64251
64421
  const operatorDir = "/run/switchroom/broker/operator";
64252
- if (operatorUidStr !== undefined && existsSync35(operatorDir)) {
64422
+ if (operatorUidStr !== undefined && existsSync36(operatorDir)) {
64253
64423
  const operatorUid = parseInt(operatorUidStr, 10);
64254
64424
  if (!Number.isFinite(operatorUid) || operatorUid <= 0) {
64255
64425
  process.stderr.write(`[vault-broker] SWITCHROOM_BROKER_OPERATOR_UID='${operatorUidStr}' is not a positive integer; skipping operator listener
@@ -64289,8 +64459,8 @@ init_client();
64289
64459
  var import_yaml10 = __toESM(require_dist(), 1);
64290
64460
  import { spawnSync as spawnSync3 } from "node:child_process";
64291
64461
  import { readFileSync as readFileSync32, writeFileSync as writeFileSync20 } from "node:fs";
64292
- import { homedir as homedir16 } from "node:os";
64293
- import { join as join31 } from "node:path";
64462
+ import { homedir as homedir17 } from "node:os";
64463
+ import { join as join32 } from "node:path";
64294
64464
  class EncryptFailedError extends Error {
64295
64465
  detail;
64296
64466
  constructor(detail) {
@@ -64323,7 +64493,7 @@ function setVaultBrokerAutoUnlock(configPath, value) {
64323
64493
  doc.setIn(["vault", "broker", "autoUnlock"], value);
64324
64494
  writeFileSync20(configPath, doc.toString(), "utf-8");
64325
64495
  }
64326
- var DEFAULT_COMPOSE_FILE = join31(homedir16(), ".switchroom", "compose", "docker-compose.yml");
64496
+ var DEFAULT_COMPOSE_FILE = join32(homedir17(), ".switchroom", "compose", "docker-compose.yml");
64327
64497
  async function applyAutoUnlock(opts = {}) {
64328
64498
  const log = opts.log ?? ((s) => console.log(s));
64329
64499
  const err = opts.err ?? ((s) => console.error(s));
@@ -64509,7 +64679,7 @@ function registerVaultBrokerCommand(vaultCmd, program3) {
64509
64679
  process.exit(0);
64510
64680
  }
64511
64681
  const pidPath = resolvePath(DEFAULT_PID_FILE);
64512
- if (!existsSync36(pidPath)) {
64682
+ if (!existsSync37(pidPath)) {
64513
64683
  console.error("vault-broker PID file not found \u2014 is the daemon running?");
64514
64684
  process.exit(1);
64515
64685
  }
@@ -64636,7 +64806,7 @@ function registerVaultBrokerCommand(vaultCmd, program3) {
64636
64806
  broker.command("disable-auto-unlock").description("Remove the auto-unlock credential file. Reconcile + restart broker after.").action(() => {
64637
64807
  const parentOpts = program3.opts();
64638
64808
  const credPath = getAutoUnlockCredPath(parentOpts.config);
64639
- if (!existsSync36(credPath)) {
64809
+ if (!existsSync37(credPath)) {
64640
64810
  console.log(`No credential file at ${credPath} \u2014 nothing to do.`);
64641
64811
  return;
64642
64812
  }
@@ -64657,7 +64827,7 @@ function registerVaultBrokerCommand(vaultCmd, program3) {
64657
64827
 
64658
64828
  // src/cli/vault-doctor.ts
64659
64829
  init_source();
64660
- import { existsSync as existsSync37 } from "node:fs";
64830
+ import { existsSync as existsSync38 } from "node:fs";
64661
64831
 
64662
64832
  // src/vault/doctor.ts
64663
64833
  var SENSITIVE_KEY_RE = /oauth(?![a-zA-Z])|token(?![a-zA-Z])|secret(?![a-zA-Z])|api[-_]?key(?![a-zA-Z])|password(?![a-zA-Z])/i;
@@ -64827,7 +64997,7 @@ function registerVaultDoctorCommand(vault, program3) {
64827
64997
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
64828
64998
  const passphrase = process.env.SWITCHROOM_VAULT_PASSPHRASE;
64829
64999
  let vaultKeys = undefined;
64830
- if (passphrase && existsSync37(vaultPath)) {
65000
+ if (passphrase && existsSync38(vaultPath)) {
64831
65001
  try {
64832
65002
  const entries = openVault(passphrase, vaultPath);
64833
65003
  vaultKeys = {};
@@ -64913,7 +65083,7 @@ Vault Doctor`));
64913
65083
 
64914
65084
  // src/cli/vault-audit.ts
64915
65085
  init_source();
64916
- import { existsSync as existsSync38, readFileSync as readFileSync34 } from "node:fs";
65086
+ import { existsSync as existsSync39, readFileSync as readFileSync34 } from "node:fs";
64917
65087
 
64918
65088
  // src/vault/audit-reader.ts
64919
65089
  function parseAuditLine(line) {
@@ -64987,7 +65157,7 @@ function formatAuditLines(rawLines, filters, limit = 50) {
64987
65157
  function registerVaultAuditCommand(vault, _program) {
64988
65158
  vault.command("audit").description("Tail and filter the vault audit log (~/.switchroom/vault-audit.log)").option("--who <caller>", "Filter by caller substring (unit name or pid)").option("--key <pattern>", "Filter by key name (regex or substring)").option("--denied", "Show only denied access attempts").option("--tail <n>", "Number of matching entries to show (default: 50)", "50").option("--path <file>", "Override audit log path (for debugging)").action((opts) => {
64989
65159
  const logPath = opts.path ?? defaultAuditLogPath();
64990
- if (!existsSync38(logPath)) {
65160
+ if (!existsSync39(logPath)) {
64991
65161
  console.error(source_default.yellow(`Audit log not found at ${logPath}.`) + source_default.gray(`
64992
65162
  The log is created when the vault broker handles its first request.`));
64993
65163
  process.exit(0);
@@ -65042,8 +65212,8 @@ init_source();
65042
65212
  init_loader();
65043
65213
  init_loader();
65044
65214
  init_client();
65045
- import { join as join32 } from "node:path";
65046
- import { homedir as homedir17 } from "node:os";
65215
+ import { join as join33 } from "node:path";
65216
+ import { homedir as homedir18 } from "node:os";
65047
65217
  function parseDuration(raw) {
65048
65218
  const lower = raw.toLowerCase().trim();
65049
65219
  if (lower === "0" || lower === "never" || lower === "none")
@@ -65135,7 +65305,7 @@ function registerVaultGrantCommands(vault, program3) {
65135
65305
  console.error(source_default.red(`Failed to mint grant: ${result.msg}`));
65136
65306
  process.exit(1);
65137
65307
  }
65138
- const tokenPath = join32(homedir17(), ".switchroom", "agents", agent, ".vault-token");
65308
+ const tokenPath = join33(homedir18(), ".switchroom", "agents", agent, ".vault-token");
65139
65309
  console.log(source_default.green(`\u2713 Grant minted`));
65140
65310
  if (process.stdout.isTTY) {
65141
65311
  console.log(source_default.bold("Token: ") + result.token);
@@ -65186,8 +65356,8 @@ The token file was written to the agent directory (mode 0600).`));
65186
65356
  // src/cli/vault-backup.ts
65187
65357
  init_source();
65188
65358
  init_loader();
65189
- import { existsSync as existsSync40 } from "node:fs";
65190
- import { join as join34 } from "node:path";
65359
+ import { existsSync as existsSync41 } from "node:fs";
65360
+ import { join as join35 } from "node:path";
65191
65361
 
65192
65362
  // src/vault/backup.ts
65193
65363
  import {
@@ -65197,20 +65367,20 @@ import {
65197
65367
  import {
65198
65368
  appendFileSync as appendFileSync2,
65199
65369
  closeSync as closeSync9,
65200
- existsSync as existsSync39,
65370
+ existsSync as existsSync40,
65201
65371
  fsyncSync as fsyncSync5,
65202
65372
  mkdirSync as mkdirSync23,
65203
65373
  openSync as openSync9,
65204
- readdirSync as readdirSync17,
65374
+ readdirSync as readdirSync18,
65205
65375
  readFileSync as readFileSync35,
65206
65376
  renameSync as renameSync11,
65207
- statSync as statSync20,
65377
+ statSync as statSync21,
65208
65378
  symlinkSync as symlinkSync4,
65209
65379
  unlinkSync as unlinkSync10,
65210
65380
  writeSync as writeSync5
65211
65381
  } from "node:fs";
65212
- import { homedir as homedir18 } from "node:os";
65213
- import { join as join33, resolve as resolvePath2 } from "node:path";
65382
+ import { homedir as homedir19 } from "node:os";
65383
+ import { join as join34, resolve as resolvePath2 } from "node:path";
65214
65384
  var LATEST_SYMLINK = "vault.enc.latest.bak";
65215
65385
  var MANIFEST_FILE = "manifest.jsonl";
65216
65386
  var DEFAULT_RETAIN = 30;
@@ -65285,9 +65455,9 @@ function resolveBackupDestination(input) {
65285
65455
  if (input.configDestination)
65286
65456
  return resolvePath2(input.configDestination);
65287
65457
  if (input.hasSwitchroomConfigRepo) {
65288
- return join33(input.home, ".switchroom-config", "vault-backups");
65458
+ return join34(input.home, ".switchroom-config", "vault-backups");
65289
65459
  }
65290
- return join33(input.home, ".switchroom", "vault-backups");
65460
+ return join34(input.home, ".switchroom", "vault-backups");
65291
65461
  }
65292
65462
  function findAutoUnlockSibling(entries) {
65293
65463
  for (const name of entries) {
@@ -65305,11 +65475,11 @@ function selectBackupsToPrune(sortedNewestFirst, retain) {
65305
65475
  return sortedNewestFirst.slice(retain);
65306
65476
  }
65307
65477
  function listBackupFiles(dir) {
65308
- if (!existsSync39(dir))
65478
+ if (!existsSync40(dir))
65309
65479
  return [];
65310
65480
  let entries;
65311
65481
  try {
65312
- entries = readdirSync17(dir);
65482
+ entries = readdirSync18(dir);
65313
65483
  } catch {
65314
65484
  return [];
65315
65485
  }
@@ -65332,15 +65502,15 @@ function backupVault(opts) {
65332
65502
  throw new Error(`vault backup refused: source is not a valid vault envelope: ${validationError}`);
65333
65503
  }
65334
65504
  mkdirSync23(opts.destDir, { recursive: true, mode: 448 });
65335
- const dirEntries = readdirSync17(opts.destDir);
65505
+ const dirEntries = readdirSync18(opts.destDir);
65336
65506
  const offender = findAutoUnlockSibling(dirEntries);
65337
65507
  if (offender) {
65338
65508
  throw new Error(`vault backup refused: destination '${opts.destDir}' contains a file ` + `that looks like an auto-unlock credential ('${offender}'). The ` + `machine-bound auto-unlock blob MUST NOT be co-located with the ` + `encrypted vault \u2014 if they're together in version control, the ` + `passphrase gate is bypassed. Move/remove that file and retry.`);
65339
65509
  }
65340
65510
  const filename = computeBackupFilename(now);
65341
- const fullPath = join33(opts.destDir, filename);
65511
+ const fullPath = join34(opts.destDir, filename);
65342
65512
  const tmpName = `.tmp.${process.pid}.${randomBytes10(4).toString("hex")}`;
65343
- const tmpPath = join33(opts.destDir, tmpName);
65513
+ const tmpPath = join34(opts.destDir, tmpName);
65344
65514
  const src = readFileSync35(opts.vaultPath);
65345
65515
  const fd = openSync9(tmpPath, "wx", 384);
65346
65516
  try {
@@ -65349,14 +65519,14 @@ function backupVault(opts) {
65349
65519
  } finally {
65350
65520
  closeSync9(fd);
65351
65521
  }
65352
- if (existsSync39(fullPath)) {
65522
+ if (existsSync40(fullPath)) {
65353
65523
  try {
65354
65524
  unlinkSync10(tmpPath);
65355
65525
  } catch {}
65356
65526
  throw new Error(`vault backup refused: '${fullPath}' already exists ` + `(sub-second collision with another backup). Retry in 1 second, ` + `or check for a concurrent backup process.`);
65357
65527
  }
65358
65528
  renameSync11(tmpPath, fullPath);
65359
- const stat = statSync20(fullPath);
65529
+ const stat = statSync21(fullPath);
65360
65530
  const sha256 = sha256OfFile(fullPath);
65361
65531
  const row = {
65362
65532
  ts: now.toISOString(),
@@ -65364,9 +65534,9 @@ function backupVault(opts) {
65364
65534
  size_bytes: stat.size,
65365
65535
  sha256
65366
65536
  };
65367
- appendFileSync2(join33(opts.destDir, MANIFEST_FILE), JSON.stringify(row) + `
65537
+ appendFileSync2(join34(opts.destDir, MANIFEST_FILE), JSON.stringify(row) + `
65368
65538
  `, { mode: 384 });
65369
- const latestPath = join33(opts.destDir, LATEST_SYMLINK);
65539
+ const latestPath = join34(opts.destDir, LATEST_SYMLINK);
65370
65540
  try {
65371
65541
  unlinkSync10(latestPath);
65372
65542
  } catch {}
@@ -65385,7 +65555,7 @@ function backupVault(opts) {
65385
65555
  const pruneNames = selectBackupsToPrune(sorted, retain);
65386
65556
  for (const old of pruneNames) {
65387
65557
  try {
65388
- unlinkSync10(join33(opts.destDir, old));
65558
+ unlinkSync10(join34(opts.destDir, old));
65389
65559
  } catch {}
65390
65560
  }
65391
65561
  if (pruneNames.length > 0) {
@@ -65408,7 +65578,7 @@ function backupVault(opts) {
65408
65578
  };
65409
65579
  }
65410
65580
  function defaultHome() {
65411
- return process.env.HOME ?? homedir18();
65581
+ return process.env.HOME ?? homedir19();
65412
65582
  }
65413
65583
 
65414
65584
  // src/cli/vault-backup.ts
@@ -65434,7 +65604,7 @@ function registerVaultBackupCommand(vault, program3) {
65434
65604
  }
65435
65605
  } catch {}
65436
65606
  const home2 = defaultHome();
65437
- const hasSwitchroomConfigRepo = existsSync40(join34(home2, ".switchroom-config"));
65607
+ const hasSwitchroomConfigRepo = existsSync41(join35(home2, ".switchroom-config"));
65438
65608
  const destDir = resolveBackupDestination({
65439
65609
  cliToFlag: opts.to ? resolvePath(opts.to) : undefined,
65440
65610
  configDestination,
@@ -66060,8 +66230,8 @@ Push passphrase to broker for future requests? [Y/n]: `);
66060
66230
 
66061
66231
  // src/cli/telegram.ts
66062
66232
  init_source();
66063
- import { existsSync as existsSync41, readFileSync as readFileSync37, writeFileSync as writeFileSync21 } from "node:fs";
66064
- import { join as join35 } from "node:path";
66233
+ import { existsSync as existsSync42, readFileSync as readFileSync37, writeFileSync as writeFileSync21 } from "node:fs";
66234
+ import { join as join36 } from "node:path";
66065
66235
 
66066
66236
  // src/web/webhook-dispatch.ts
66067
66237
  function renderTemplate2(template, ctx) {
@@ -66323,8 +66493,8 @@ async function runTopicsDiscover(program3, chatId, opts) {
66323
66493
  fail(`Unknown agent '${agentName}'. Check switchroom.yaml.`);
66324
66494
  }
66325
66495
  const agentsDir = process.env.SWITCHROOM_AGENTS_DIR ?? resolveStatePath("agents");
66326
- const dbPath = join35(agentsDir, agentName, "telegram", "history.db");
66327
- if (!existsSync41(dbPath)) {
66496
+ const dbPath = join36(agentsDir, agentName, "telegram", "history.db");
66497
+ if (!existsSync42(dbPath)) {
66328
66498
  fail(`No history DB at ${dbPath}.
66329
66499
  ` + ` The agent may not have received any Telegram messages yet, or it may be offline.
66330
66500
  ` + ` Tip: send one message in each topic of the supergroup, then re-run this command.`);
@@ -66592,7 +66762,7 @@ async function vaultPut(program3, key, value) {
66592
66762
  const configPath = program3.optsWithGlobals().config ?? undefined;
66593
66763
  const vaultPath = resolveVaultPath(configPath);
66594
66764
  const passphrase = await getVaultPassphrase();
66595
- if (!existsSync41(vaultPath)) {
66765
+ if (!existsSync42(vaultPath)) {
66596
66766
  createVault(passphrase, vaultPath);
66597
66767
  console.log(source_default.gray(` Created new vault at ${vaultPath}`));
66598
66768
  }
@@ -66988,11 +67158,11 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
66988
67158
  // src/cli/memory.ts
66989
67159
  init_loader();
66990
67160
  var import_yaml12 = __toESM(require_dist(), 1);
66991
- import { existsSync as existsSync42, readFileSync as readFileSync38, writeFileSync as writeFileSync22 } from "node:fs";
66992
- import { join as join36 } from "node:path";
67161
+ import { existsSync as existsSync43, readFileSync as readFileSync38, writeFileSync as writeFileSync22 } from "node:fs";
67162
+ import { join as join37 } from "node:path";
66993
67163
  function readRecallLog(agentDir, limit) {
66994
- const path4 = join36(agentDir, ".claude", "plugins", "data", "hindsight-memory-inline", "state", "recall_log.jsonl");
66995
- if (!existsSync42(path4))
67164
+ const path4 = join37(agentDir, ".claude", "plugins", "data", "hindsight-memory-inline", "state", "recall_log.jsonl");
67165
+ if (!existsSync43(path4))
66996
67166
  return [];
66997
67167
  let raw;
66998
67168
  try {
@@ -67190,7 +67360,7 @@ Cross-agent reflection plan
67190
67360
  const url = `http://127.0.0.1:${ports.apiPort}/mcp/`;
67191
67361
  const configPath = getConfigPath(program3);
67192
67362
  try {
67193
- if (existsSync42(configPath)) {
67363
+ if (existsSync43(configPath)) {
67194
67364
  const raw = readFileSync38(configPath, "utf-8");
67195
67365
  const doc = import_yaml12.default.parseDocument(raw);
67196
67366
  if (!doc.has("memory")) {
@@ -67232,7 +67402,7 @@ Cross-agent reflection plan
67232
67402
  process.exit(1);
67233
67403
  })() : Object.keys(config.agents);
67234
67404
  for (const name of targets) {
67235
- const agentDir = join36(agentsDir, name);
67405
+ const agentDir = join37(agentsDir, name);
67236
67406
  const entries = readRecallLog(agentDir, limit);
67237
67407
  if (opts.json) {
67238
67408
  for (const e of entries) {
@@ -67300,16 +67470,16 @@ init_loader();
67300
67470
  init_lifecycle();
67301
67471
  import {
67302
67472
  readFileSync as readFileSync44,
67303
- existsSync as existsSync48,
67304
- realpathSync as realpathSync3,
67473
+ existsSync as existsSync49,
67474
+ realpathSync as realpathSync4,
67305
67475
  mkdirSync as mkdirSync28,
67306
67476
  openSync as openSync10,
67307
67477
  closeSync as closeSync10,
67308
67478
  writeSync as writeSync6,
67309
67479
  constants as fsConstants3
67310
67480
  } from "node:fs";
67311
- import { resolve as resolve28, extname, join as join43, relative, dirname as dirname9 } from "node:path";
67312
- import { homedir as homedir23 } from "node:os";
67481
+ import { resolve as resolve28, extname, join as join44, relative, dirname as dirname10 } from "node:path";
67482
+ import { homedir as homedir24 } from "node:os";
67313
67483
  import { spawn as spawn5 } from "node:child_process";
67314
67484
  import { timingSafeEqual as timingSafeEqual3, randomBytes as randomBytes11 } from "node:crypto";
67315
67485
 
@@ -67318,7 +67488,7 @@ init_lifecycle();
67318
67488
  init_manager();
67319
67489
  init_hindsight();
67320
67490
  import { spawnSync as spawnSync5 } from "node:child_process";
67321
- import { existsSync as existsSync45, readFileSync as readFileSync41, statSync as statSync21 } from "node:fs";
67491
+ import { existsSync as existsSync46, readFileSync as readFileSync41, statSync as statSync22 } from "node:fs";
67322
67492
  import { resolve as resolve27 } from "node:path";
67323
67493
  init_audit_reader();
67324
67494
 
@@ -67382,7 +67552,7 @@ function readRecentFires(jsonlPath) {
67382
67552
  init_client3();
67383
67553
 
67384
67554
  // node_modules/.bun/posthog-node@5.29.2/node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
67385
- import { dirname as dirname7, posix, sep as sep2 } from "path";
67555
+ import { dirname as dirname8, posix, sep as sep2 } from "path";
67386
67556
  function createModulerModifier() {
67387
67557
  const getModuleFromFileName = createGetModuleFromFilename();
67388
67558
  return async (frames) => {
@@ -67391,7 +67561,7 @@ function createModulerModifier() {
67391
67561
  return frames;
67392
67562
  };
67393
67563
  }
67394
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname7(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
67564
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname8(process.argv[1]) : process.cwd(), isWindows = sep2 === "\\") {
67395
67565
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
67396
67566
  return (filename) => {
67397
67567
  if (!filename)
@@ -71824,12 +71994,12 @@ class PostHog extends PostHogBackendClient {
71824
71994
  // src/analytics/posthog.ts
71825
71995
  init_paths();
71826
71996
  import {
71827
- existsSync as existsSync43,
71997
+ existsSync as existsSync44,
71828
71998
  mkdirSync as mkdirSync24,
71829
71999
  readFileSync as readFileSync39,
71830
72000
  writeFileSync as writeFileSync23
71831
72001
  } from "node:fs";
71832
- import { dirname as dirname8 } from "node:path";
72002
+ import { dirname as dirname9 } from "node:path";
71833
72003
  import { randomUUID as randomUUID3 } from "node:crypto";
71834
72004
  var DEFAULT_KEY = "phc_qKY87cKWZm6ZyCtk7LcRd2cU8Sg42u7Ywhui5stYCegd";
71835
72005
  var DEFAULT_HOST = "https://us.i.posthog.com";
@@ -71846,7 +72016,7 @@ function getDistinctId() {
71846
72016
  return cachedDistinctId;
71847
72017
  const path4 = resolveStatePath("analytics-id");
71848
72018
  try {
71849
- if (existsSync43(path4)) {
72019
+ if (existsSync44(path4)) {
71850
72020
  const existing = readFileSync39(path4, "utf-8").trim();
71851
72021
  if (existing) {
71852
72022
  cachedDistinctId = existing;
@@ -71857,7 +72027,7 @@ function getDistinctId() {
71857
72027
  const id = randomUUID3();
71858
72028
  cachedDistinctId = id;
71859
72029
  try {
71860
- mkdirSync24(dirname8(path4), { recursive: true });
72030
+ mkdirSync24(dirname9(path4), { recursive: true });
71861
72031
  writeFileSync23(path4, id, "utf-8");
71862
72032
  } catch {}
71863
72033
  return id;
@@ -72028,19 +72198,19 @@ import {
72028
72198
  } from "node:fs";
72029
72199
  import { spawnSync as spawnSync4 } from "node:child_process";
72030
72200
  import { tmpdir as tmpdir4 } from "node:os";
72031
- import { join as join38 } from "node:path";
72201
+ import { join as join39 } from "node:path";
72032
72202
 
72033
72203
  class ConfigDiffError extends Error {
72034
72204
  }
72035
72205
  function generateUnifiedDiff(before, after, name = "switchroom.yaml", gitBin = "git") {
72036
72206
  if (before === after)
72037
72207
  return "";
72038
- const dir = mkdtemp(join38(tmpdir4(), "switchroom-config-diff-"));
72208
+ const dir = mkdtemp(join39(tmpdir4(), "switchroom-config-diff-"));
72039
72209
  try {
72040
- mkdirSync25(join38(dir, "cur"), { recursive: true });
72041
- mkdirSync25(join38(dir, "new"), { recursive: true });
72042
- writeFileSync24(join38(dir, "cur", name), before);
72043
- writeFileSync24(join38(dir, "new", name), after);
72210
+ mkdirSync25(join39(dir, "cur"), { recursive: true });
72211
+ mkdirSync25(join39(dir, "new"), { recursive: true });
72212
+ writeFileSync24(join39(dir, "cur", name), before);
72213
+ writeFileSync24(join39(dir, "new", name), after);
72044
72214
  const r = spawnSync4(gitBin, ["diff", "--no-index", "--no-color", "--", `cur/${name}`, `new/${name}`], { cwd: dir, encoding: "utf-8", timeout: 1e4 });
72045
72215
  if (r.status === 0)
72046
72216
  return "";
@@ -72072,9 +72242,9 @@ function generateUnifiedDiff(before, after, name = "switchroom.yaml", gitBin = "
72072
72242
 
72073
72243
  // src/web/hostd-config-propose.ts
72074
72244
  init_client4();
72075
- import { existsSync as existsSync44 } from "node:fs";
72076
- import { homedir as homedir20 } from "node:os";
72077
- import { join as join39 } from "node:path";
72245
+ import { existsSync as existsSync45 } from "node:fs";
72246
+ import { homedir as homedir21 } from "node:os";
72247
+ import { join as join40 } from "node:path";
72078
72248
  var PROPOSE_TIMEOUT_MS = 11 * 60 * 1000;
72079
72249
  function resolveHostdOperatorSocket(env2 = process.env) {
72080
72250
  const override = env2.SWITCHROOM_HOSTD_OPERATOR_SOCKET;
@@ -72082,10 +72252,10 @@ function resolveHostdOperatorSocket(env2 = process.env) {
72082
72252
  return override;
72083
72253
  const candidates = [
72084
72254
  "/host-home/.switchroom/hostd/operator/sock",
72085
- join39(homedir20(), ".switchroom", "hostd", "operator", "sock")
72255
+ join40(homedir21(), ".switchroom", "hostd", "operator", "sock")
72086
72256
  ];
72087
72257
  for (const c of candidates) {
72088
- if (existsSync44(c))
72258
+ if (existsSync45(c))
72089
72259
  return c;
72090
72260
  }
72091
72261
  return null;
@@ -72178,7 +72348,7 @@ init_client2();
72178
72348
 
72179
72349
  // telegram-plugin/registry/turns-schema.ts
72180
72350
  import { chmodSync as chmodSync8, mkdirSync as mkdirSync26 } from "fs";
72181
- import { join as join40 } from "path";
72351
+ import { join as join41 } from "path";
72182
72352
  var DatabaseClass = null;
72183
72353
  function loadDatabaseClass() {
72184
72354
  if (DatabaseClass != null)
@@ -72241,9 +72411,9 @@ function applySchema(db) {
72241
72411
  }
72242
72412
  function openTurnsDb(agentDir) {
72243
72413
  const Database2 = loadDatabaseClass();
72244
- const dir = join40(agentDir, "telegram");
72414
+ const dir = join41(agentDir, "telegram");
72245
72415
  mkdirSync26(dir, { recursive: true, mode: 448 });
72246
- const path4 = join40(dir, "registry.db");
72416
+ const path4 = join41(dir, "registry.db");
72247
72417
  const db = new Database2(path4, { create: true });
72248
72418
  applySchema(db);
72249
72419
  try {
@@ -72350,7 +72520,7 @@ function listSubagents(db, opts = {}) {
72350
72520
  function agentBridgeAlive(agentsDir, name, maxAgeMs = 30000, now = Date.now()) {
72351
72521
  try {
72352
72522
  const f = resolve27(agentsDir, name, "telegram", ".bridge-alive");
72353
- return now - statSync21(f).mtimeMs <= maxAgeMs;
72523
+ return now - statSync22(f).mtimeMs <= maxAgeMs;
72354
72524
  } catch {
72355
72525
  return false;
72356
72526
  }
@@ -72675,7 +72845,7 @@ async function handleGetSystemHealth(config, home2) {
72675
72845
  };
72676
72846
  try {
72677
72847
  const logPath = defaultAuditLogPath2(home2);
72678
- if (existsSync45(logPath)) {
72848
+ if (existsSync46(logPath)) {
72679
72849
  hostd.auditLogPresent = true;
72680
72850
  const raw = readFileSync41(logPath, "utf-8");
72681
72851
  hostd.recent = readAndFilter(raw, {}, 10);
@@ -72977,9 +73147,9 @@ async function handleGetApprovals() {
72977
73147
  }
72978
73148
 
72979
73149
  // src/web/webhook-handler.ts
72980
- import { appendFileSync as appendFileSync3, existsSync as existsSync47, mkdirSync as mkdirSync27, readFileSync as readFileSync43, writeFileSync as writeFileSync25 } from "fs";
72981
- import { join as join42 } from "path";
72982
- import { homedir as homedir22 } from "os";
73150
+ import { appendFileSync as appendFileSync3, existsSync as existsSync48, mkdirSync as mkdirSync27, readFileSync as readFileSync43, writeFileSync as writeFileSync25 } from "fs";
73151
+ import { join as join43 } from "path";
73152
+ import { homedir as homedir23 } from "os";
72983
73153
 
72984
73154
  // src/web/webhook-verify.ts
72985
73155
  import { createHmac as createHmac2, timingSafeEqual } from "crypto";
@@ -73129,18 +73299,18 @@ function forwardToGateway(socketPath, req, opts = {}) {
73129
73299
  }
73130
73300
 
73131
73301
  // src/web/webhook-edge.ts
73132
- import { existsSync as existsSync46, readFileSync as readFileSync42 } from "fs";
73133
- import { join as join41 } from "path";
73134
- import { homedir as homedir21 } from "os";
73302
+ import { existsSync as existsSync47, readFileSync as readFileSync42 } from "fs";
73303
+ import { join as join42 } from "path";
73304
+ import { homedir as homedir22 } from "os";
73135
73305
  import { timingSafeEqual as timingSafeEqual2 } from "crypto";
73136
73306
  var EDGE_HEADER = "x-switchroom-edge";
73137
73307
  function edgeSecretPath() {
73138
- return join41(homedir21(), ".switchroom", "webhook-edge-secret");
73308
+ return join42(homedir22(), ".switchroom", "webhook-edge-secret");
73139
73309
  }
73140
73310
  function loadEdgeSecret(path4) {
73141
73311
  const p = path4 ?? edgeSecretPath();
73142
73312
  try {
73143
- if (!existsSync46(p))
73313
+ if (!existsSync47(p))
73144
73314
  return null;
73145
73315
  const raw = readFileSync42(p, "utf-8").trim();
73146
73316
  return raw.length > 0 ? raw : null;
@@ -73174,7 +73344,7 @@ var DEDUP_MAX = 1000;
73174
73344
  var DEDUP_TTL_MS = 24 * 60 * 60 * 1000;
73175
73345
  function loadDedupFile(path4) {
73176
73346
  try {
73177
- if (!existsSync47(path4))
73347
+ if (!existsSync48(path4))
73178
73348
  return {};
73179
73349
  const raw = JSON.parse(readFileSync43(path4, "utf-8"));
73180
73350
  return typeof raw.deliveries === "object" && raw.deliveries !== null ? raw.deliveries : {};
@@ -73198,8 +73368,8 @@ var agentDedupCache = new Map;
73198
73368
  function createFileDedupStore(resolveAgentDir) {
73199
73369
  return {
73200
73370
  check(agent, deliveryId, now) {
73201
- const telegramDir = join42(resolveAgentDir(agent), "telegram");
73202
- const filePath = join42(telegramDir, "webhook-dedup.json");
73371
+ const telegramDir = join43(resolveAgentDir(agent), "telegram");
73372
+ const filePath = join43(telegramDir, "webhook-dedup.json");
73203
73373
  if (!agentDedupCache.has(agent)) {
73204
73374
  agentDedupCache.set(agent, loadDedupFile(filePath));
73205
73375
  }
@@ -73251,7 +73421,7 @@ function shouldWriteThrottleIssue(agent, source, now, windowMap) {
73251
73421
  return true;
73252
73422
  }
73253
73423
  function writeThrottleIssue(agent, source, now, telegramDir, log) {
73254
- const issuesPath = join42(telegramDir, "issues.jsonl");
73424
+ const issuesPath = join43(telegramDir, "issues.jsonl");
73255
73425
  try {
73256
73426
  mkdirSync27(telegramDir, { recursive: true });
73257
73427
  const record = {
@@ -73276,7 +73446,7 @@ function writeThrottleIssue(agent, source, now, telegramDir, log) {
73276
73446
  async function handleWebhookIngest(args, deps = {}) {
73277
73447
  const log = deps.log ?? ((s) => process.stderr.write(s));
73278
73448
  const now = (deps.now ?? Date.now)();
73279
- const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join42(homedir22(), ".switchroom", "agents", a));
73449
+ const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join43(homedir23(), ".switchroom", "agents", a));
73280
73450
  const rateLimiter = deps.rateLimiter ?? defaultRateLimiter;
73281
73451
  const dedupStore = deps.dedupStore ?? createFileDedupStore(resolveAgentDir);
73282
73452
  if (!args.agentExists) {
@@ -73340,7 +73510,7 @@ async function handleWebhookIngest(args, deps = {}) {
73340
73510
  if (retryAfter !== null) {
73341
73511
  if (!args.viaGateway) {
73342
73512
  const agentDir2 = resolveAgentDir(args.agent);
73343
- const telegramDir2 = join42(agentDir2, "telegram");
73513
+ const telegramDir2 = join43(agentDir2, "telegram");
73344
73514
  if (shouldWriteThrottleIssue(args.agent, source, now)) {
73345
73515
  writeThrottleIssue(args.agent, source, now, telegramDir2, log);
73346
73516
  }
@@ -73360,7 +73530,7 @@ async function handleWebhookIngest(args, deps = {}) {
73360
73530
  const eventType = source === "github" ? args.headers.get("x-github-event") ?? "unknown" : args.source;
73361
73531
  const rendered = source === "github" ? renderGithubEvent(eventType, payload) : renderGenericEvent(args.source, payload);
73362
73532
  if (args.viaGateway) {
73363
- const socketPath = join42(resolveAgentDir(args.agent), "telegram", "webhook.sock");
73533
+ const socketPath = join43(resolveAgentDir(args.agent), "telegram", "webhook.sock");
73364
73534
  const forward = deps.forwardFn ?? forwardToGateway;
73365
73535
  const deliveryId = source === "github" ? args.headers.get("x-github-delivery") ?? undefined : undefined;
73366
73536
  let resp;
@@ -73399,8 +73569,8 @@ async function handleWebhookIngest(args, deps = {}) {
73399
73569
  return jsonReply(202, { ok: true, recorded: true, ts: resp.ts });
73400
73570
  }
73401
73571
  const agentDir = resolveAgentDir(args.agent);
73402
- const telegramDir = join42(agentDir, "telegram");
73403
- const logPath = join42(telegramDir, "webhook-events.jsonl");
73572
+ const telegramDir = join43(agentDir, "telegram");
73573
+ const logPath = join43(telegramDir, "webhook-events.jsonl");
73404
73574
  try {
73405
73575
  mkdirSync27(telegramDir, { recursive: true });
73406
73576
  const record = {
@@ -73453,15 +73623,15 @@ function resolveWebToken() {
73453
73623
  const fromEnv = process.env.SWITCHROOM_WEB_TOKEN;
73454
73624
  if (fromEnv && fromEnv.length > 0)
73455
73625
  return fromEnv;
73456
- const home2 = process.env.HOME ?? homedir23();
73457
- const tokenPath = join43(home2, ".switchroom", "web-token");
73458
- if (existsSync48(tokenPath)) {
73626
+ const home2 = process.env.HOME ?? homedir24();
73627
+ const tokenPath = join44(home2, ".switchroom", "web-token");
73628
+ if (existsSync49(tokenPath)) {
73459
73629
  const existing = readFileSync44(tokenPath, "utf8").trim();
73460
73630
  if (existing.length > 0)
73461
73631
  return existing;
73462
73632
  }
73463
73633
  const token = randomBytes11(32).toString("hex");
73464
- mkdirSync28(dirname9(tokenPath), { recursive: true, mode: 448 });
73634
+ mkdirSync28(dirname10(tokenPath), { recursive: true, mode: 448 });
73465
73635
  try {
73466
73636
  const fd = openSync10(tokenPath, fsConstants3.O_WRONLY | fsConstants3.O_CREAT | fsConstants3.O_EXCL, 384);
73467
73637
  try {
@@ -73539,8 +73709,8 @@ function checkWsAuth(req, token, server) {
73539
73709
  return presented !== null && constantTimeEqual(presented, token);
73540
73710
  }
73541
73711
  function loadWebhookSecrets() {
73542
- const path4 = join43(homedir23(), ".switchroom", "webhook-secrets.json");
73543
- if (!existsSync48(path4))
73712
+ const path4 = join44(homedir24(), ".switchroom", "webhook-secrets.json");
73713
+ if (!existsSync49(path4))
73544
73714
  return {};
73545
73715
  try {
73546
73716
  const parsed = JSON.parse(readFileSync44(path4, "utf-8"));
@@ -73673,7 +73843,7 @@ function parseRoute(pathname, method) {
73673
73843
  }
73674
73844
  function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
73675
73845
  const uiDirRaw = resolve28(import.meta.dirname, "ui");
73676
- const uiDir = existsSync48(uiDirRaw) ? realpathSync3(uiDirRaw) : uiDirRaw;
73846
+ const uiDir = existsSync49(uiDirRaw) ? realpathSync4(uiDirRaw) : uiDirRaw;
73677
73847
  const token = resolveWebToken();
73678
73848
  const freshConfig = () => {
73679
73849
  if (!configPath)
@@ -73870,13 +74040,13 @@ function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
73870
74040
  }
73871
74041
  }
73872
74042
  let filePath = pathname === "/" ? "/index.html" : pathname;
73873
- const fullPath = join43(uiDir, filePath);
73874
- if (!existsSync48(fullPath)) {
74043
+ const fullPath = join44(uiDir, filePath);
74044
+ if (!existsSync49(fullPath)) {
73875
74045
  return new Response("Not Found", { status: 404 });
73876
74046
  }
73877
74047
  let realFullPath;
73878
74048
  try {
73879
- realFullPath = realpathSync3(fullPath);
74049
+ realFullPath = realpathSync4(fullPath);
73880
74050
  } catch {
73881
74051
  return new Response("Not Found", { status: 404 });
73882
74052
  }
@@ -74020,8 +74190,8 @@ Starting Switchroom dashboard...
74020
74190
  // src/cli/setup.ts
74021
74191
  init_source();
74022
74192
  init_loader();
74023
- import { existsSync as existsSync49, copyFileSync as copyFileSync8, readFileSync as readFileSync45, writeFileSync as writeFileSync26, mkdirSync as mkdirSync29 } from "node:fs";
74024
- import { resolve as resolve29, dirname as dirname10 } from "node:path";
74193
+ import { existsSync as existsSync50, copyFileSync as copyFileSync8, readFileSync as readFileSync45, writeFileSync as writeFileSync26, mkdirSync as mkdirSync29 } from "node:fs";
74194
+ import { resolve as resolve29, dirname as dirname11 } from "node:path";
74025
74195
  init_vault();
74026
74196
  init_manager();
74027
74197
 
@@ -74202,7 +74372,7 @@ async function stepConfigFile(configPath, nonInteractive) {
74202
74372
  existingConfig = null;
74203
74373
  }
74204
74374
  }
74205
- if (existingConfig && existsSync49(existingConfig)) {
74375
+ if (existingConfig && existsSync50(existingConfig)) {
74206
74376
  if (!nonInteractive) {
74207
74377
  const useExisting = await askYesNo(` Found ${source_default.cyan(existingConfig)}. Use it?`, true);
74208
74378
  if (!useExisting) {
@@ -74230,10 +74400,10 @@ async function copyExampleConfig(nonInteractive) {
74230
74400
  }
74231
74401
  const srcFile = resolve29(examplesDir, `${choice}.yaml`);
74232
74402
  const destFile = resolvePath("~/.switchroom/switchroom.yaml");
74233
- if (!existsSync49(srcFile)) {
74403
+ if (!existsSync50(srcFile)) {
74234
74404
  throw new ConfigError(`Example config not found: ${choice}.yaml`);
74235
74405
  }
74236
- mkdirSync29(dirname10(destFile), { recursive: true });
74406
+ mkdirSync29(dirname11(destFile), { recursive: true });
74237
74407
  copyFileSync8(srcFile, destFile);
74238
74408
  console.log(source_default.green(` Copied ${choice}.yaml -> ${destFile}`));
74239
74409
  console.log(source_default.yellow(` Edit ${destFile} to customize, then re-run switchroom setup.`));
@@ -74314,7 +74484,7 @@ async function resolveOrPromptToken(rawToken, label, config, nonInteractive) {
74314
74484
  try {
74315
74485
  const { openVault: openVault2 } = await Promise.resolve().then(() => (init_vault(), exports_vault));
74316
74486
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
74317
- if (existsSync49(vaultPath)) {
74487
+ if (existsSync50(vaultPath)) {
74318
74488
  const secrets = openVault2(passphrase, vaultPath);
74319
74489
  const key = rawToken.replace("vault:", "");
74320
74490
  const entry = secrets[key];
@@ -74342,7 +74512,7 @@ async function resolveOrPromptToken(rawToken, label, config, nonInteractive) {
74342
74512
  async function storeTokenInVault(config, vaultRef, token) {
74343
74513
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
74344
74514
  const key = vaultRef.replace("vault:", "");
74345
- if (!existsSync49(vaultPath)) {
74515
+ if (!existsSync50(vaultPath)) {
74346
74516
  console.log(source_default.gray(" Creating encrypted vault..."));
74347
74517
  let passphrase = process.env.SWITCHROOM_VAULT_PASSPHRASE;
74348
74518
  if (!passphrase) {
@@ -74515,7 +74685,7 @@ async function stepMemoryBackend(config, nonInteractive, switchroomConfigPath) {
74515
74685
  try {
74516
74686
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
74517
74687
  const passphrase = process.env.SWITCHROOM_VAULT_PASSPHRASE;
74518
- if (passphrase && existsSync49(vaultPath)) {
74688
+ if (passphrase && existsSync50(vaultPath)) {
74519
74689
  const existing = getStringSecret(passphrase, vaultPath, "hindsight-api-key");
74520
74690
  if (existing) {
74521
74691
  console.log(source_default.gray(" Note: legacy 'hindsight-api-key' is in your vault but is no longer used. You can remove it with `switchroom vault rm hindsight-api-key`."));
@@ -74675,13 +74845,13 @@ async function stepAutoUnlock(config, switchroomConfigPath, nonInteractive) {
74675
74845
  return;
74676
74846
  }
74677
74847
  const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
74678
- if (!existsSync49(vaultPath)) {
74848
+ if (!existsSync50(vaultPath)) {
74679
74849
  console.log(source_default.gray(" Skipping (vault not created yet)."));
74680
74850
  return;
74681
74851
  }
74682
74852
  const credPathRaw = config.vault?.broker?.autoUnlockCredentialPath ?? "~/.switchroom/vault-auto-unlock";
74683
74853
  const credPath = resolvePath(credPathRaw);
74684
- if (config.vault?.broker?.autoUnlock === true && existsSync49(credPath)) {
74854
+ if (config.vault?.broker?.autoUnlock === true && existsSync50(credPath)) {
74685
74855
  console.log(source_default.green(` ${STEP_DONE} Already configured (${credPath})`));
74686
74856
  return;
74687
74857
  }
@@ -74747,8 +74917,8 @@ async function stepAutoUnlock(config, switchroomConfigPath, nonInteractive) {
74747
74917
  const choice = await askChoice(" Approval posture", [PASSPHRASE_CHOICE, TELEGRAM_ID_CHOICE]);
74748
74918
  if (choice === TELEGRAM_ID_CHOICE) {
74749
74919
  try {
74750
- const yamlPath = existsSync49(resolve29(process.cwd(), "switchroom.yaml")) ? resolve29(process.cwd(), "switchroom.yaml") : resolve29(process.cwd(), "switchroom.yml");
74751
- if (existsSync49(yamlPath)) {
74920
+ const yamlPath = existsSync50(resolve29(process.cwd(), "switchroom.yaml")) ? resolve29(process.cwd(), "switchroom.yaml") : resolve29(process.cwd(), "switchroom.yml");
74921
+ if (existsSync50(yamlPath)) {
74752
74922
  const content = readFileSync45(yamlPath, "utf-8");
74753
74923
  const result = insertVaultBrokerApprovalAuth(content, "telegram-id");
74754
74924
  if (result.kind === "rewritten") {
@@ -74783,7 +74953,7 @@ async function stepDangerousMode(config, nonInteractive) {
74783
74953
  resolve29(process.cwd(), "switchroom.yml")
74784
74954
  ];
74785
74955
  for (const configPath of configPaths) {
74786
- if (existsSync49(configPath)) {
74956
+ if (existsSync50(configPath)) {
74787
74957
  let content = readFileSync45(configPath, "utf-8");
74788
74958
  const agentNames = Object.keys(config.agents);
74789
74959
  for (const name of agentNames) {
@@ -74913,22 +75083,22 @@ init_doctor();
74913
75083
  init_source();
74914
75084
  init_loader();
74915
75085
  init_lifecycle();
74916
- import { cpSync as cpSync2, existsSync as existsSync56, mkdirSync as mkdirSync31, readFileSync as readFileSync50, realpathSync as realpathSync5, rmSync as rmSync12, statSync as statSync25 } from "node:fs";
75086
+ import { cpSync as cpSync2, existsSync as existsSync57, mkdirSync as mkdirSync31, readFileSync as readFileSync50, realpathSync as realpathSync6, rmSync as rmSync12, statSync as statSync26 } from "node:fs";
74917
75087
  import { spawnSync as spawnSync9 } from "node:child_process";
74918
- import { join as join57, dirname as dirname13, resolve as resolve33 } from "node:path";
74919
- import { homedir as homedir34 } from "node:os";
74920
- var DEFAULT_COMPOSE_PATH = join57(homedir34(), ".switchroom", "compose", "docker-compose.yml");
75088
+ import { join as join58, dirname as dirname14, resolve as resolve33 } from "node:path";
75089
+ import { homedir as homedir35 } from "node:os";
75090
+ var DEFAULT_COMPOSE_PATH = join58(homedir35(), ".switchroom", "compose", "docker-compose.yml");
74921
75091
  function runningFromSwitchroomCheckout(scriptPath) {
74922
- let dir = dirname13(scriptPath);
75092
+ let dir = dirname14(scriptPath);
74923
75093
  for (let i = 0;i < 12; i++) {
74924
- if (existsSync56(join57(dir, ".git"))) {
75094
+ if (existsSync57(join58(dir, ".git"))) {
74925
75095
  try {
74926
- const pkg = JSON.parse(readFileSync50(join57(dir, "package.json"), "utf-8"));
75096
+ const pkg = JSON.parse(readFileSync50(join58(dir, "package.json"), "utf-8"));
74927
75097
  if (pkg.name === "switchroom")
74928
75098
  return true;
74929
75099
  } catch {}
74930
75100
  }
74931
- const parent = dirname13(dir);
75101
+ const parent = dirname14(dir);
74932
75102
  if (parent === dir)
74933
75103
  break;
74934
75104
  dir = parent;
@@ -74975,7 +75145,7 @@ function planUpdate(opts) {
74975
75145
  steps.push({
74976
75146
  name: "pull-images",
74977
75147
  description: "Pull broker / kernel / agent images from GHCR",
74978
- skipReason: opts.skipImages ? "--skip-images flag set" : !existsSync56(composePath) ? `compose file not found at ${composePath} (run \`switchroom apply --compose-only\` first)` : undefined,
75148
+ skipReason: opts.skipImages ? "--skip-images flag set" : !existsSync57(composePath) ? `compose file not found at ${composePath} (run \`switchroom apply --compose-only\` first)` : undefined,
74979
75149
  run: () => {
74980
75150
  const r = runner("docker", [
74981
75151
  "compose",
@@ -75074,17 +75244,17 @@ function planUpdate(opts) {
75074
75244
  return;
75075
75245
  }
75076
75246
  const source = resolve33(import.meta.dirname, "../../skills");
75077
- const dest = join57(homedir34(), ".switchroom", "skills", "_bundled");
75078
- if (!existsSync56(source)) {
75247
+ const dest = join58(homedir35(), ".switchroom", "skills", "_bundled");
75248
+ if (!existsSync57(source)) {
75079
75249
  process.stderr.write(`switchroom update: sync-bundled-skills \u2014 CLI bundle has no adjacent skills/ at ${source}; skipping.
75080
75250
  `);
75081
75251
  return;
75082
75252
  }
75083
75253
  try {
75084
- if (existsSync56(dest)) {
75254
+ if (existsSync57(dest)) {
75085
75255
  rmSync12(dest, { recursive: true, force: true });
75086
75256
  }
75087
- mkdirSync31(dirname13(dest), { recursive: true });
75257
+ mkdirSync31(dirname14(dest), { recursive: true });
75088
75258
  cpSync2(source, dest, { recursive: true, dereference: false });
75089
75259
  } catch (err) {
75090
75260
  throw new Error(`sync-bundled-skills failed: ${err.message}`);
@@ -75180,16 +75350,16 @@ function defaultStatusProbe(composePath) {
75180
75350
  let scriptPath = rawScriptPath;
75181
75351
  try {
75182
75352
  if (rawScriptPath)
75183
- scriptPath = realpathSync5(rawScriptPath);
75353
+ scriptPath = realpathSync6(rawScriptPath);
75184
75354
  } catch {}
75185
75355
  if (scriptPath) {
75186
75356
  try {
75187
- cliBuiltAt = new Date(statSync25(scriptPath).mtimeMs).toISOString();
75357
+ cliBuiltAt = new Date(statSync26(scriptPath).mtimeMs).toISOString();
75188
75358
  } catch {}
75189
- let dir = dirname13(scriptPath);
75359
+ let dir = dirname14(scriptPath);
75190
75360
  for (let i = 0;i < 8; i++) {
75191
- const pkgPath = join57(dir, "package.json");
75192
- if (existsSync56(pkgPath)) {
75361
+ const pkgPath = join58(dir, "package.json");
75362
+ if (existsSync57(pkgPath)) {
75193
75363
  try {
75194
75364
  const pkg = JSON.parse(readFileSync50(pkgPath, "utf-8"));
75195
75365
  if (typeof pkg.version === "string")
@@ -75199,7 +75369,7 @@ function defaultStatusProbe(composePath) {
75199
75369
  }
75200
75370
  break;
75201
75371
  }
75202
- const parent = dirname13(dir);
75372
+ const parent = dirname14(dir);
75203
75373
  if (parent === dir)
75204
75374
  break;
75205
75375
  dir = parent;
@@ -75212,7 +75382,7 @@ function defaultStatusProbe(composePath) {
75212
75382
  warnings.push("could not resolve CLI version (no package.json found above the resolved script path)");
75213
75383
  }
75214
75384
  const services = [];
75215
- if (!existsSync56(composePath)) {
75385
+ if (!existsSync57(composePath)) {
75216
75386
  warnings.push(`compose file not found at ${composePath}; service status unknown`);
75217
75387
  return { cliVersion, cliBuiltAt, services, warnings };
75218
75388
  }
@@ -75407,8 +75577,8 @@ init_source();
75407
75577
  init_helpers();
75408
75578
  init_lifecycle();
75409
75579
  import { execSync as execSync4 } from "node:child_process";
75410
- import { existsSync as existsSync57, readFileSync as readFileSync51 } from "node:fs";
75411
- import { dirname as dirname14, join as join58 } from "node:path";
75580
+ import { existsSync as existsSync58, readFileSync as readFileSync51 } from "node:fs";
75581
+ import { dirname as dirname15, join as join59 } from "node:path";
75412
75582
  function getClaudeCodeVersion() {
75413
75583
  try {
75414
75584
  const out = execSync4("claude --version 2>/dev/null", {
@@ -75458,16 +75628,16 @@ function formatUptime3(timestamp) {
75458
75628
  function locateSwitchroomInstallDir() {
75459
75629
  let dir = import.meta.dirname;
75460
75630
  for (let i = 0;i < 10 && dir && dir !== "/"; i++) {
75461
- const pkgPath = join58(dir, "package.json");
75462
- if (existsSync57(pkgPath)) {
75631
+ const pkgPath = join59(dir, "package.json");
75632
+ if (existsSync58(pkgPath)) {
75463
75633
  try {
75464
75634
  const pkg = JSON.parse(readFileSync51(pkgPath, "utf-8"));
75465
- if (pkg.name === "switchroom" && existsSync57(join58(dir, ".git"))) {
75635
+ if (pkg.name === "switchroom" && existsSync58(join59(dir, ".git"))) {
75466
75636
  return dir;
75467
75637
  }
75468
75638
  } catch {}
75469
75639
  }
75470
- dir = dirname14(dir);
75640
+ dir = dirname15(dir);
75471
75641
  }
75472
75642
  return null;
75473
75643
  }
@@ -75688,18 +75858,18 @@ function registerHandoffCommand(program3) {
75688
75858
  // src/issues/store.ts
75689
75859
  import {
75690
75860
  closeSync as closeSync11,
75691
- existsSync as existsSync58,
75861
+ existsSync as existsSync59,
75692
75862
  mkdirSync as mkdirSync32,
75693
75863
  openSync as openSync11,
75694
- readdirSync as readdirSync21,
75864
+ readdirSync as readdirSync22,
75695
75865
  readFileSync as readFileSync52,
75696
75866
  renameSync as renameSync12,
75697
- statSync as statSync26,
75867
+ statSync as statSync27,
75698
75868
  unlinkSync as unlinkSync11,
75699
75869
  writeFileSync as writeFileSync27,
75700
75870
  writeSync as writeSync7
75701
75871
  } from "node:fs";
75702
- import { join as join59 } from "node:path";
75872
+ import { join as join60 } from "node:path";
75703
75873
  import { randomBytes as randomBytes12 } from "node:crypto";
75704
75874
  import { execSync as execSync5 } from "node:child_process";
75705
75875
 
@@ -76097,8 +76267,8 @@ function redactedMarker(ruleId) {
76097
76267
  var ISSUES_FILE = "issues.jsonl";
76098
76268
  var ISSUES_LOCK = "issues.lock";
76099
76269
  function readAll(stateDir) {
76100
- const path4 = join59(stateDir, ISSUES_FILE);
76101
- if (!existsSync58(path4))
76270
+ const path4 = join60(stateDir, ISSUES_FILE);
76271
+ if (!existsSync59(path4))
76102
76272
  return [];
76103
76273
  let raw;
76104
76274
  try {
@@ -76175,7 +76345,7 @@ function record(stateDir, input, nowFn = Date.now) {
76175
76345
  });
76176
76346
  }
76177
76347
  function resolve36(stateDir, fingerprint, nowFn = Date.now) {
76178
- if (!existsSync58(join59(stateDir, ISSUES_FILE)))
76348
+ if (!existsSync59(join60(stateDir, ISSUES_FILE)))
76179
76349
  return 0;
76180
76350
  return withLock(stateDir, () => {
76181
76351
  const all = readAll(stateDir);
@@ -76193,7 +76363,7 @@ function resolve36(stateDir, fingerprint, nowFn = Date.now) {
76193
76363
  });
76194
76364
  }
76195
76365
  function resolveAllBySource(stateDir, source, nowFn = Date.now) {
76196
- if (!existsSync58(join59(stateDir, ISSUES_FILE)))
76366
+ if (!existsSync59(join60(stateDir, ISSUES_FILE)))
76197
76367
  return 0;
76198
76368
  return withLock(stateDir, () => {
76199
76369
  const all = readAll(stateDir);
@@ -76211,7 +76381,7 @@ function resolveAllBySource(stateDir, source, nowFn = Date.now) {
76211
76381
  });
76212
76382
  }
76213
76383
  function prune(stateDir, opts = {}) {
76214
- if (!existsSync58(join59(stateDir, ISSUES_FILE)))
76384
+ if (!existsSync59(join60(stateDir, ISSUES_FILE)))
76215
76385
  return 0;
76216
76386
  return withLock(stateDir, () => {
76217
76387
  const all = readAll(stateDir);
@@ -76244,7 +76414,7 @@ function ensureDir(stateDir) {
76244
76414
  mkdirSync32(stateDir, { recursive: true });
76245
76415
  }
76246
76416
  function writeAll(stateDir, events) {
76247
- const path4 = join59(stateDir, ISSUES_FILE);
76417
+ const path4 = join60(stateDir, ISSUES_FILE);
76248
76418
  sweepOrphanTmpFiles(stateDir);
76249
76419
  const tmp = `${path4}.tmp-${process.pid}-${randomBytes12(4).toString("hex")}`;
76250
76420
  const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
@@ -76258,7 +76428,7 @@ var TMP_PREFIX = `${ISSUES_FILE}.tmp-`;
76258
76428
  function sweepOrphanTmpFiles(stateDir) {
76259
76429
  let entries;
76260
76430
  try {
76261
- entries = readdirSync21(stateDir);
76431
+ entries = readdirSync22(stateDir);
76262
76432
  } catch {
76263
76433
  return;
76264
76434
  }
@@ -76266,9 +76436,9 @@ function sweepOrphanTmpFiles(stateDir) {
76266
76436
  for (const entry of entries) {
76267
76437
  if (!entry.startsWith(TMP_PREFIX))
76268
76438
  continue;
76269
- const tmpPath = join59(stateDir, entry);
76439
+ const tmpPath = join60(stateDir, entry);
76270
76440
  try {
76271
- const stat = statSync26(tmpPath);
76441
+ const stat = statSync27(tmpPath);
76272
76442
  if (stat.mtimeMs < cutoff) {
76273
76443
  unlinkSync11(tmpPath);
76274
76444
  }
@@ -76278,7 +76448,7 @@ function sweepOrphanTmpFiles(stateDir) {
76278
76448
  var LOCK_RETRY_MS = 25;
76279
76449
  var LOCK_TIMEOUT_MS = 1e4;
76280
76450
  function withLock(stateDir, fn) {
76281
- const lockPath = join59(stateDir, ISSUES_LOCK);
76451
+ const lockPath = join60(stateDir, ISSUES_LOCK);
76282
76452
  const startedAt = Date.now();
76283
76453
  let fd = null;
76284
76454
  while (fd === null) {
@@ -76561,21 +76731,21 @@ function relTime(deltaMs) {
76561
76731
 
76562
76732
  // src/cli/deps.ts
76563
76733
  init_source();
76564
- import { existsSync as existsSync61 } from "node:fs";
76565
- import { homedir as homedir37 } from "node:os";
76566
- import { join as join62, resolve as resolve37 } from "node:path";
76734
+ import { existsSync as existsSync62 } from "node:fs";
76735
+ import { homedir as homedir38 } from "node:os";
76736
+ import { join as join63, resolve as resolve37 } from "node:path";
76567
76737
 
76568
76738
  // src/deps/python.ts
76569
76739
  import { createHash as createHash11 } from "node:crypto";
76570
76740
  import {
76571
- existsSync as existsSync59,
76741
+ existsSync as existsSync60,
76572
76742
  mkdirSync as mkdirSync33,
76573
76743
  readFileSync as readFileSync53,
76574
76744
  rmSync as rmSync13,
76575
76745
  writeFileSync as writeFileSync28
76576
76746
  } from "node:fs";
76577
- import { dirname as dirname15, join as join60 } from "node:path";
76578
- import { homedir as homedir35 } from "node:os";
76747
+ import { dirname as dirname16, join as join61 } from "node:path";
76748
+ import { homedir as homedir36 } from "node:os";
76579
76749
  import { execFileSync as execFileSync19 } from "node:child_process";
76580
76750
 
76581
76751
  class PythonEnvError extends Error {
@@ -76587,7 +76757,7 @@ class PythonEnvError extends Error {
76587
76757
  }
76588
76758
  }
76589
76759
  function defaultPythonCacheRoot() {
76590
- return join60(homedir35(), ".switchroom", "deps", "python");
76760
+ return join61(homedir36(), ".switchroom", "deps", "python");
76591
76761
  }
76592
76762
  function hashFile(path4) {
76593
76763
  return createHash11("sha256").update(readFileSync53(path4)).digest("hex");
@@ -76596,16 +76766,16 @@ function ensurePythonEnv(opts) {
76596
76766
  const { skillName, requirementsPath, force = false } = opts;
76597
76767
  const cacheRoot = opts.cacheRoot ?? defaultPythonCacheRoot();
76598
76768
  const hostPython = opts.pythonBin ?? "python3";
76599
- if (!existsSync59(requirementsPath)) {
76769
+ if (!existsSync60(requirementsPath)) {
76600
76770
  throw new PythonEnvError(`requirements file not found: ${requirementsPath}`);
76601
76771
  }
76602
- const venvDir = join60(cacheRoot, skillName);
76603
- const stampPath = join60(venvDir, ".requirements.sha256");
76604
- const binDir = join60(venvDir, "bin");
76605
- const pythonBin = join60(binDir, "python");
76606
- const pipBin = join60(binDir, "pip");
76772
+ const venvDir = join61(cacheRoot, skillName);
76773
+ const stampPath = join61(venvDir, ".requirements.sha256");
76774
+ const binDir = join61(venvDir, "bin");
76775
+ const pythonBin = join61(binDir, "python");
76776
+ const pipBin = join61(binDir, "pip");
76607
76777
  const targetHash = hashFile(requirementsPath);
76608
- if (!force && existsSync59(stampPath) && existsSync59(pythonBin)) {
76778
+ if (!force && existsSync60(stampPath) && existsSync60(pythonBin)) {
76609
76779
  const existingHash = readFileSync53(stampPath, "utf8").trim();
76610
76780
  if (existingHash === targetHash) {
76611
76781
  return {
@@ -76618,10 +76788,10 @@ function ensurePythonEnv(opts) {
76618
76788
  };
76619
76789
  }
76620
76790
  }
76621
- if (existsSync59(venvDir)) {
76791
+ if (existsSync60(venvDir)) {
76622
76792
  rmSync13(venvDir, { recursive: true, force: true });
76623
76793
  }
76624
- mkdirSync33(dirname15(venvDir), { recursive: true });
76794
+ mkdirSync33(dirname16(venvDir), { recursive: true });
76625
76795
  try {
76626
76796
  execFileSync19(hostPython, ["-m", "venv", venvDir], { stdio: "pipe" });
76627
76797
  } catch (err) {
@@ -76656,14 +76826,14 @@ function ensurePythonEnv(opts) {
76656
76826
  import { createHash as createHash12 } from "node:crypto";
76657
76827
  import {
76658
76828
  copyFileSync as copyFileSync9,
76659
- existsSync as existsSync60,
76829
+ existsSync as existsSync61,
76660
76830
  mkdirSync as mkdirSync34,
76661
76831
  readFileSync as readFileSync54,
76662
76832
  rmSync as rmSync14,
76663
76833
  writeFileSync as writeFileSync29
76664
76834
  } from "node:fs";
76665
- import { dirname as dirname16, join as join61 } from "node:path";
76666
- import { homedir as homedir36 } from "node:os";
76835
+ import { dirname as dirname17, join as join62 } from "node:path";
76836
+ import { homedir as homedir37 } from "node:os";
76667
76837
  import { execFileSync as execFileSync20 } from "node:child_process";
76668
76838
 
76669
76839
  class NodeEnvError extends Error {
@@ -76686,17 +76856,17 @@ var LOCKFILES_FOR = {
76686
76856
  npm: ["package-lock.json"]
76687
76857
  };
76688
76858
  function defaultNodeCacheRoot() {
76689
- return join61(homedir36(), ".switchroom", "deps", "node");
76859
+ return join62(homedir37(), ".switchroom", "deps", "node");
76690
76860
  }
76691
76861
  function hashDepInputs(packageJsonPath) {
76692
- const sourceDir = dirname16(packageJsonPath);
76862
+ const sourceDir = dirname17(packageJsonPath);
76693
76863
  const hasher = createHash12("sha256");
76694
76864
  hasher.update(`package.json
76695
76865
  `);
76696
76866
  hasher.update(readFileSync54(packageJsonPath));
76697
76867
  for (const lockName of ALL_LOCKFILES) {
76698
- const lockPath = join61(sourceDir, lockName);
76699
- if (existsSync60(lockPath)) {
76868
+ const lockPath = join62(sourceDir, lockName);
76869
+ if (existsSync61(lockPath)) {
76700
76870
  hasher.update(`
76701
76871
  `);
76702
76872
  hasher.update(lockName);
@@ -76711,16 +76881,16 @@ function ensureNodeEnv(opts) {
76711
76881
  const { skillName, packageJsonPath, force = false } = opts;
76712
76882
  const cacheRoot = opts.cacheRoot ?? defaultNodeCacheRoot();
76713
76883
  const installer = opts.installer ?? "bun";
76714
- if (!existsSync60(packageJsonPath)) {
76884
+ if (!existsSync61(packageJsonPath)) {
76715
76885
  throw new NodeEnvError(`package.json not found: ${packageJsonPath}`);
76716
76886
  }
76717
- const sourceDir = dirname16(packageJsonPath);
76718
- const envDir = join61(cacheRoot, skillName);
76719
- const stampPath = join61(envDir, ".package.sha256");
76720
- const nodeModulesDir = join61(envDir, "node_modules");
76721
- const binDir = join61(nodeModulesDir, ".bin");
76887
+ const sourceDir = dirname17(packageJsonPath);
76888
+ const envDir = join62(cacheRoot, skillName);
76889
+ const stampPath = join62(envDir, ".package.sha256");
76890
+ const nodeModulesDir = join62(envDir, "node_modules");
76891
+ const binDir = join62(nodeModulesDir, ".bin");
76722
76892
  const targetHash = hashDepInputs(packageJsonPath);
76723
- if (!force && existsSync60(stampPath) && existsSync60(nodeModulesDir)) {
76893
+ if (!force && existsSync61(stampPath) && existsSync61(nodeModulesDir)) {
76724
76894
  const existingHash = readFileSync54(stampPath, "utf8").trim();
76725
76895
  if (existingHash === targetHash) {
76726
76896
  return {
@@ -76732,16 +76902,16 @@ function ensureNodeEnv(opts) {
76732
76902
  };
76733
76903
  }
76734
76904
  }
76735
- if (existsSync60(envDir)) {
76905
+ if (existsSync61(envDir)) {
76736
76906
  rmSync14(envDir, { recursive: true, force: true });
76737
76907
  }
76738
76908
  mkdirSync34(envDir, { recursive: true });
76739
- copyFileSync9(packageJsonPath, join61(envDir, "package.json"));
76909
+ copyFileSync9(packageJsonPath, join62(envDir, "package.json"));
76740
76910
  let copiedLockfile = false;
76741
76911
  for (const lockName of LOCKFILES_FOR[installer]) {
76742
- const lockPath = join61(sourceDir, lockName);
76743
- if (existsSync60(lockPath)) {
76744
- copyFileSync9(lockPath, join61(envDir, lockName));
76912
+ const lockPath = join62(sourceDir, lockName);
76913
+ if (existsSync61(lockPath)) {
76914
+ copyFileSync9(lockPath, join62(envDir, lockName));
76745
76915
  copiedLockfile = true;
76746
76916
  }
76747
76917
  }
@@ -76770,28 +76940,28 @@ function ensureNodeEnv(opts) {
76770
76940
 
76771
76941
  // src/cli/deps.ts
76772
76942
  function builtinSkillsRoot() {
76773
- return resolve37(homedir37(), ".switchroom/skills/_bundled");
76943
+ return resolve37(homedir38(), ".switchroom/skills/_bundled");
76774
76944
  }
76775
76945
  function registerDepsCommand(program3) {
76776
76946
  const deps = program3.command("deps").description("Manage cached per-skill dependency environments");
76777
76947
  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) => {
76778
76948
  const skillsRoot = builtinSkillsRoot();
76779
- if (!existsSync61(skillsRoot)) {
76949
+ if (!existsSync62(skillsRoot)) {
76780
76950
  console.error(source_default.red(`Bundled skills pool dir not found at ${skillsRoot} \u2014 run \`switchroom update\` to install it.`));
76781
76951
  process.exit(1);
76782
76952
  }
76783
- const skillDir = join62(skillsRoot, skill);
76784
- if (!existsSync61(skillDir)) {
76953
+ const skillDir = join63(skillsRoot, skill);
76954
+ if (!existsSync62(skillDir)) {
76785
76955
  console.error(source_default.red(`Unknown skill: ${skill} (no dir at ${skillDir})`));
76786
76956
  process.exit(1);
76787
76957
  }
76788
- const requirementsPath = join62(skillDir, "requirements.txt");
76789
- const packageJsonPath = join62(skillDir, "package.json");
76790
- const wantPython = opts.python ?? (!opts.python && !opts.node && existsSync61(requirementsPath));
76791
- const wantNode = opts.node ?? (!opts.python && !opts.node && existsSync61(packageJsonPath));
76958
+ const requirementsPath = join63(skillDir, "requirements.txt");
76959
+ const packageJsonPath = join63(skillDir, "package.json");
76960
+ const wantPython = opts.python ?? (!opts.python && !opts.node && existsSync62(requirementsPath));
76961
+ const wantNode = opts.node ?? (!opts.python && !opts.node && existsSync62(packageJsonPath));
76792
76962
  let did = 0;
76793
76963
  if (wantPython) {
76794
- if (!existsSync61(requirementsPath)) {
76964
+ if (!existsSync62(requirementsPath)) {
76795
76965
  console.error(source_default.red(`Skill "${skill}" has no requirements.txt at ${requirementsPath}`));
76796
76966
  process.exit(1);
76797
76967
  }
@@ -76815,7 +76985,7 @@ function registerDepsCommand(program3) {
76815
76985
  }
76816
76986
  }
76817
76987
  if (wantNode) {
76818
- if (!existsSync61(packageJsonPath)) {
76988
+ if (!existsSync62(packageJsonPath)) {
76819
76989
  console.error(source_default.red(`Skill "${skill}" has no package.json at ${packageJsonPath}`));
76820
76990
  process.exit(1);
76821
76991
  }
@@ -76848,12 +77018,12 @@ function registerDepsCommand(program3) {
76848
77018
  // src/cli/workspace.ts
76849
77019
  init_helpers();
76850
77020
  init_loader();
76851
- import { existsSync as existsSync62 } from "node:fs";
77021
+ import { existsSync as existsSync63 } from "node:fs";
76852
77022
  import { resolve as resolve38, sep as sep3 } from "node:path";
76853
77023
  import { spawnSync as spawnSync10 } from "node:child_process";
76854
77024
 
76855
77025
  // src/agents/workspace.ts
76856
- import { readFile, stat } from "node:fs/promises";
77026
+ import { readFile as readFile2, stat } from "node:fs/promises";
76857
77027
  import path5 from "node:path";
76858
77028
 
76859
77029
  // src/agents/bootstrap-budget.ts
@@ -77091,7 +77261,7 @@ function resolveAgentWorkspaceDir(agentDir) {
77091
77261
  }
77092
77262
  async function readOptionalFile(filePath) {
77093
77263
  try {
77094
- const content = await readFile(filePath, "utf8");
77264
+ const content = await readFile2(filePath, "utf8");
77095
77265
  return content;
77096
77266
  } catch (err) {
77097
77267
  if (isErrnoException(err) && (err.code === "ENOENT" || err.code === "EISDIR")) {
@@ -77281,7 +77451,7 @@ async function buildDynamicBootstrapPrompt(params) {
77281
77451
  }
77282
77452
 
77283
77453
  // src/agents/memory-search.ts
77284
- import { readFile as readFile2, readdir, realpath, stat as stat2 } from "node:fs/promises";
77454
+ import { readFile as readFile3, readdir, realpath, stat as stat2 } from "node:fs/promises";
77285
77455
  import path6 from "node:path";
77286
77456
  var DEFAULT_MEMORY_SEARCH_MAX_RESULTS = 6;
77287
77457
  var DEFAULT_MEMORY_SEARCH_SNIPPET_CHARS = 220;
@@ -77332,7 +77502,7 @@ async function loadIndex(workspaceDir) {
77332
77502
  break;
77333
77503
  let content;
77334
77504
  try {
77335
- content = await readFile2(full, "utf8");
77505
+ content = await readFile3(full, "utf8");
77336
77506
  } catch {
77337
77507
  continue;
77338
77508
  }
@@ -77463,7 +77633,7 @@ async function getWorkspaceMemoryFile(params) {
77463
77633
  if (!info.isFile()) {
77464
77634
  throw new Error(`not a file: ${params.relativePath}`);
77465
77635
  }
77466
- const buf = await readFile2(resolvedTarget);
77636
+ const buf = await readFile3(resolvedTarget);
77467
77637
  if (buf.length <= maxBytes) {
77468
77638
  return {
77469
77639
  path: params.relativePath,
@@ -77627,7 +77797,7 @@ function registerWorkspaceCommand(program3) {
77627
77797
  if (!dir)
77628
77798
  return;
77629
77799
  const gitDir = resolve38(dir, ".git");
77630
- if (!existsSync62(gitDir)) {
77800
+ if (!existsSync63(gitDir)) {
77631
77801
  process.stdout.write(`Workspace is not a git repository. Re-run \`switchroom agent create ${agentName}\` ` + `or manually \`git init\` in ${dir} to enable versioning.
77632
77802
  `);
77633
77803
  return;
@@ -77681,7 +77851,7 @@ function registerWorkspaceCommand(program3) {
77681
77851
  if (!dir)
77682
77852
  return;
77683
77853
  const gitDir = resolve38(dir, ".git");
77684
- if (!existsSync62(gitDir)) {
77854
+ if (!existsSync63(gitDir)) {
77685
77855
  process.stdout.write(`Workspace is not a git repository.
77686
77856
  `);
77687
77857
  return;
@@ -77706,7 +77876,7 @@ function resolveAgentWorkspaceDirOrExit(program3, agentName) {
77706
77876
  const agentsDir = resolveAgentsDir(config);
77707
77877
  const agentDir = resolve38(agentsDir, agentName);
77708
77878
  const dir = resolveAgentWorkspaceDir(agentDir);
77709
- if (!existsSync62(dir)) {
77879
+ if (!existsSync63(dir)) {
77710
77880
  process.stderr.write(`workspace: ${dir} does not exist yet. Run \`switchroom setup\` or \`switchroom agent scaffold ${agentName}\` to seed it.
77711
77881
  `);
77712
77882
  return;
@@ -77742,8 +77912,8 @@ function safeParseInt(value, fallback) {
77742
77912
  init_helpers();
77743
77913
  init_loader();
77744
77914
  init_merge();
77745
- import { copyFileSync as copyFileSync10, existsSync as existsSync63, readFileSync as readFileSync55, writeFileSync as writeFileSync30 } from "node:fs";
77746
- import { join as join63, resolve as resolve39 } from "node:path";
77915
+ import { copyFileSync as copyFileSync10, existsSync as existsSync64, readFileSync as readFileSync55, writeFileSync as writeFileSync30 } from "node:fs";
77916
+ import { join as join64, resolve as resolve39 } from "node:path";
77747
77917
  init_schema();
77748
77918
  function resolveSoulTargetOrExit(program3, agentName) {
77749
77919
  const config = getConfig(program3);
@@ -77758,7 +77928,7 @@ function resolveSoulTargetOrExit(program3, agentName) {
77758
77928
  const agentsDir = resolveAgentsDir(config);
77759
77929
  const agentDir = resolve39(agentsDir, agentName);
77760
77930
  const workspaceDir = resolveAgentWorkspaceDir(agentDir);
77761
- if (!existsSync63(workspaceDir)) {
77931
+ if (!existsSync64(workspaceDir)) {
77762
77932
  console.error(`soul: ${workspaceDir} does not exist yet. Run \`switchroom setup\` ` + `or \`switchroom agent scaffold ${agentName}\` to seed it.`);
77763
77933
  process.exit(1);
77764
77934
  }
@@ -77767,7 +77937,7 @@ function resolveSoulTargetOrExit(program3, agentName) {
77767
77937
  profileName,
77768
77938
  profilePath,
77769
77939
  workspaceDir,
77770
- soulPath: join63(workspaceDir, "SOUL.md"),
77940
+ soulPath: join64(workspaceDir, "SOUL.md"),
77771
77941
  soul: merged.soul
77772
77942
  };
77773
77943
  }
@@ -77784,7 +77954,7 @@ function registerSoulCommand(program3) {
77784
77954
  const t = resolveSoulTargetOrExit(program3, agentName);
77785
77955
  if (!t)
77786
77956
  return;
77787
- if (!existsSync63(t.soulPath)) {
77957
+ if (!existsSync64(t.soulPath)) {
77788
77958
  console.error(`soul: ${t.soulPath} does not exist yet \u2014 run ` + `\`switchroom soul reset ${agentName}\` to seed it.`);
77789
77959
  process.exit(1);
77790
77960
  }
@@ -77799,7 +77969,7 @@ function registerSoulCommand(program3) {
77799
77969
  console.error(`soul: profile "${t.profileName}" ships no SOUL.md.hbs \u2014 ` + `nothing to re-seed from.`);
77800
77970
  process.exit(1);
77801
77971
  }
77802
- const exists = existsSync63(t.soulPath);
77972
+ const exists = existsSync64(t.soulPath);
77803
77973
  if (exists && !opts.yes) {
77804
77974
  if (!isInteractive()) {
77805
77975
  console.error(`soul: ${t.soulPath} already exists. Re-run with --yes to ` + `replace it (the current file is backed up to SOUL.md.bak).`);
@@ -77814,7 +77984,7 @@ function registerSoulCommand(program3) {
77814
77984
  let backupPath;
77815
77985
  if (exists) {
77816
77986
  backupPath = `${t.soulPath}.bak`;
77817
- if (existsSync63(backupPath)) {
77987
+ if (existsSync64(backupPath)) {
77818
77988
  backupPath = `${t.soulPath}.bak.${Date.now()}`;
77819
77989
  }
77820
77990
  copyFileSync10(t.soulPath, backupPath);
@@ -77833,8 +78003,8 @@ function registerSoulCommand(program3) {
77833
78003
  // src/cli/debug.ts
77834
78004
  init_helpers();
77835
78005
  init_loader();
77836
- import { existsSync as existsSync64, readFileSync as readFileSync56, readdirSync as readdirSync22, statSync as statSync27 } from "node:fs";
77837
- import { resolve as resolve40, join as join64 } from "node:path";
78006
+ import { existsSync as existsSync65, readFileSync as readFileSync56, readdirSync as readdirSync23, statSync as statSync28 } from "node:fs";
78007
+ import { resolve as resolve40, join as join65 } from "node:path";
77838
78008
  import { createHash as createHash13 } from "node:crypto";
77839
78009
  init_merge();
77840
78010
  init_hindsight();
@@ -77845,8 +78015,8 @@ function estimateTokens(bytes) {
77845
78015
  return Math.round(bytes / 3.7);
77846
78016
  }
77847
78017
  function readMcpServerNames(agentDir) {
77848
- const mcpPath = join64(agentDir, ".mcp.json");
77849
- if (!existsSync64(mcpPath))
78018
+ const mcpPath = join65(agentDir, ".mcp.json");
78019
+ if (!existsSync65(mcpPath))
77850
78020
  return [];
77851
78021
  try {
77852
78022
  const parsed = JSON.parse(readFileSync56(mcpPath, "utf-8"));
@@ -77859,20 +78029,20 @@ function sha256(content) {
77859
78029
  return createHash13("sha256").update(content).digest("hex").slice(0, 16);
77860
78030
  }
77861
78031
  function findLatestTranscriptJsonl(claudeConfigDir) {
77862
- const projectsDir = join64(claudeConfigDir, "projects");
77863
- if (!existsSync64(projectsDir))
78032
+ const projectsDir = join65(claudeConfigDir, "projects");
78033
+ if (!existsSync65(projectsDir))
77864
78034
  return;
77865
78035
  try {
77866
- const entries = readdirSync22(projectsDir, { withFileTypes: true });
78036
+ const entries = readdirSync23(projectsDir, { withFileTypes: true });
77867
78037
  let latest;
77868
78038
  for (const entry of entries) {
77869
78039
  if (!entry.isDirectory())
77870
78040
  continue;
77871
- const projectPath = join64(projectsDir, entry.name);
77872
- const transcriptPath = join64(projectPath, "transcript.jsonl");
77873
- if (!existsSync64(transcriptPath))
78041
+ const projectPath = join65(projectsDir, entry.name);
78042
+ const transcriptPath = join65(projectPath, "transcript.jsonl");
78043
+ if (!existsSync65(transcriptPath))
77874
78044
  continue;
77875
- const stat3 = statSync27(transcriptPath);
78045
+ const stat3 = statSync28(transcriptPath);
77876
78046
  if (!latest || stat3.mtimeMs > latest.mtime) {
77877
78047
  latest = { path: transcriptPath, mtime: stat3.mtimeMs };
77878
78048
  }
@@ -77933,16 +78103,16 @@ function registerDebugCommand(program3) {
77933
78103
  }
77934
78104
  const agentsDir = resolveAgentsDir(config);
77935
78105
  const agentDir = resolve40(agentsDir, agentName);
77936
- if (!existsSync64(agentDir)) {
78106
+ if (!existsSync65(agentDir)) {
77937
78107
  console.error(`Agent directory not found: ${agentDir}`);
77938
78108
  process.exit(1);
77939
78109
  }
77940
78110
  const workspaceDir = resolveAgentWorkspaceDir(agentDir);
77941
- const claudeConfigDir = join64(agentDir, ".claude");
77942
- const claudeMdPath = join64(agentDir, "CLAUDE.md");
77943
- const soulMdPath = join64(agentDir, "SOUL.md");
77944
- const workspaceSoulMdPath = join64(workspaceDir, "SOUL.md");
77945
- const handoffPath = join64(agentDir, ".handoff.md");
78111
+ const claudeConfigDir = join65(agentDir, ".claude");
78112
+ const claudeMdPath = join65(agentDir, "CLAUDE.md");
78113
+ const soulMdPath = join65(agentDir, "SOUL.md");
78114
+ const workspaceSoulMdPath = join65(workspaceDir, "SOUL.md");
78115
+ const handoffPath = join65(agentDir, ".handoff.md");
77946
78116
  const lastN = parseInt(opts.last, 10);
77947
78117
  if (isNaN(lastN) || lastN < 1) {
77948
78118
  console.error("--last must be a positive integer");
@@ -77988,7 +78158,7 @@ function registerDebugCommand(program3) {
77988
78158
  }
77989
78159
  console.log(`=== Append System Prompt (per-session) ===
77990
78160
  `);
77991
- const handoffContent = existsSync64(handoffPath) ? readFileSync56(handoffPath, "utf-8") : "";
78161
+ const handoffContent = existsSync65(handoffPath) ? readFileSync56(handoffPath, "utf-8") : "";
77992
78162
  if (handoffContent.trim().length > 0) {
77993
78163
  console.log(`-- Handoff Briefing (${formatBytes(handoffContent.length)}) --`);
77994
78164
  console.log(handoffContent);
@@ -77999,7 +78169,7 @@ function registerDebugCommand(program3) {
77999
78169
  }
78000
78170
  console.log(`=== CLAUDE.md (auto-loaded by Claude Code) ===
78001
78171
  `);
78002
- const claudeMdContent = existsSync64(claudeMdPath) ? readFileSync56(claudeMdPath, "utf-8") : "";
78172
+ const claudeMdContent = existsSync65(claudeMdPath) ? readFileSync56(claudeMdPath, "utf-8") : "";
78003
78173
  if (claudeMdContent.trim().length > 0) {
78004
78174
  console.log(`(${formatBytes(claudeMdContent.length)})`);
78005
78175
  console.log(claudeMdContent);
@@ -78010,7 +78180,7 @@ function registerDebugCommand(program3) {
78010
78180
  }
78011
78181
  console.log(`=== Persona (SOUL.md) ===
78012
78182
  `);
78013
- const soulMdContent = existsSync64(soulMdPath) ? readFileSync56(soulMdPath, "utf-8") : existsSync64(workspaceSoulMdPath) ? readFileSync56(workspaceSoulMdPath, "utf-8") : "";
78183
+ const soulMdContent = existsSync65(soulMdPath) ? readFileSync56(soulMdPath, "utf-8") : existsSync65(workspaceSoulMdPath) ? readFileSync56(workspaceSoulMdPath, "utf-8") : "";
78014
78184
  if (soulMdContent.trim().length > 0) {
78015
78185
  console.log(`(${formatBytes(soulMdContent.length)})`);
78016
78186
  console.log(soulMdContent);
@@ -78071,11 +78241,11 @@ function registerDebugCommand(program3) {
78071
78241
  const soulMdBytes = soulMdContent.length;
78072
78242
  const perTurnBytes = dynamicResult.concatenated.length;
78073
78243
  const userBytes = userMessage?.text.length ?? 0;
78074
- const fleetDir = join64(agentsDir, "..", "fleet");
78075
- const fleetInvPath = join64(fleetDir, "switchroom-invariants.md");
78076
- const fleetClaudePath = join64(fleetDir, "CLAUDE.md");
78077
- const fleetInvBytes = existsSync64(fleetInvPath) ? readFileSync56(fleetInvPath, "utf-8").length : 0;
78078
- const fleetClaudeBytes = existsSync64(fleetClaudePath) ? readFileSync56(fleetClaudePath, "utf-8").length : 0;
78244
+ const fleetDir = join65(agentsDir, "..", "fleet");
78245
+ const fleetInvPath = join65(fleetDir, "switchroom-invariants.md");
78246
+ const fleetClaudePath = join65(fleetDir, "CLAUDE.md");
78247
+ const fleetInvBytes = existsSync65(fleetInvPath) ? readFileSync56(fleetInvPath, "utf-8").length : 0;
78248
+ const fleetClaudeBytes = existsSync65(fleetClaudePath) ? readFileSync56(fleetClaudePath, "utf-8").length : 0;
78079
78249
  const fleetBytes = fleetInvBytes + fleetClaudeBytes;
78080
78250
  const totalBytes = stableBytes + perSessionBytes + claudeMdBytes + fleetBytes + perTurnBytes + userBytes;
78081
78251
  console.log(`Stable prefix: ${formatBytes(stableBytes).padEnd(20)} (cache-hot; includes SOUL.md ${soulMdBytes.toLocaleString()}B)`);
@@ -78108,9 +78278,9 @@ init_source();
78108
78278
 
78109
78279
  // src/worktree/claim.ts
78110
78280
  import { execFileSync as execFileSync21 } from "node:child_process";
78111
- import { closeSync as closeSync12, mkdirSync as mkdirSync36, openSync as openSync12, existsSync as existsSync66, unlinkSync as unlinkSync13 } from "node:fs";
78112
- import { join as join66, resolve as resolve42 } from "node:path";
78113
- import { homedir as homedir39 } from "node:os";
78281
+ import { closeSync as closeSync12, mkdirSync as mkdirSync36, openSync as openSync12, existsSync as existsSync67, unlinkSync as unlinkSync13 } from "node:fs";
78282
+ import { join as join67, resolve as resolve42 } from "node:path";
78283
+ import { homedir as homedir40 } from "node:os";
78114
78284
  import { randomBytes as randomBytes13 } from "node:crypto";
78115
78285
 
78116
78286
  // src/worktree/registry.ts
@@ -78118,18 +78288,18 @@ import {
78118
78288
  mkdirSync as mkdirSync35,
78119
78289
  writeFileSync as writeFileSync31,
78120
78290
  readFileSync as readFileSync57,
78121
- readdirSync as readdirSync23,
78291
+ readdirSync as readdirSync24,
78122
78292
  unlinkSync as unlinkSync12,
78123
- existsSync as existsSync65,
78293
+ existsSync as existsSync66,
78124
78294
  renameSync as renameSync13
78125
78295
  } from "node:fs";
78126
- import { join as join65, resolve as resolve41 } from "node:path";
78127
- import { homedir as homedir38 } from "node:os";
78296
+ import { join as join66, resolve as resolve41 } from "node:path";
78297
+ import { homedir as homedir39 } from "node:os";
78128
78298
  function registryDir() {
78129
- return resolve41(process.env.SWITCHROOM_WORKTREE_DIR ?? join65(homedir38(), ".switchroom", "worktrees"));
78299
+ return resolve41(process.env.SWITCHROOM_WORKTREE_DIR ?? join66(homedir39(), ".switchroom", "worktrees"));
78130
78300
  }
78131
78301
  function recordPath(id) {
78132
- return join65(registryDir(), `${id}.json`);
78302
+ return join66(registryDir(), `${id}.json`);
78133
78303
  }
78134
78304
  function ensureDir2() {
78135
78305
  mkdirSync35(registryDir(), { recursive: true });
@@ -78161,7 +78331,7 @@ function listRecords() {
78161
78331
  ensureDir2();
78162
78332
  const dir = registryDir();
78163
78333
  const records = [];
78164
- for (const entry of readdirSync23(dir)) {
78334
+ for (const entry of readdirSync24(dir)) {
78165
78335
  if (!entry.endsWith(".json"))
78166
78336
  continue;
78167
78337
  const id = entry.slice(0, -5);
@@ -78180,7 +78350,7 @@ function acquireRepoLock(repoPath) {
78180
78350
  const lockDir = registryDir();
78181
78351
  mkdirSync36(lockDir, { recursive: true });
78182
78352
  const lockName = repoPath.replace(/[^A-Za-z0-9]/g, "_");
78183
- const lockPath = join66(lockDir, `.lock-${lockName}`);
78353
+ const lockPath = join67(lockDir, `.lock-${lockName}`);
78184
78354
  const deadline = Date.now() + 5000;
78185
78355
  let fd = null;
78186
78356
  while (fd === null) {
@@ -78207,7 +78377,7 @@ function acquireRepoLock(repoPath) {
78207
78377
  }
78208
78378
  var DEFAULT_CONCURRENCY = 5;
78209
78379
  function worktreesBaseDir() {
78210
- return resolve42(process.env.SWITCHROOM_WORKTREE_BASE ?? join66(homedir39(), ".switchroom", "worktree-checkouts"));
78380
+ return resolve42(process.env.SWITCHROOM_WORKTREE_BASE ?? join67(homedir40(), ".switchroom", "worktree-checkouts"));
78211
78381
  }
78212
78382
  function shortId() {
78213
78383
  return randomBytes13(4).toString("hex");
@@ -78229,12 +78399,12 @@ function resolveRepoPath(repo, codeRepos) {
78229
78399
  }
78230
78400
  function expandHome(p) {
78231
78401
  if (p.startsWith("~/"))
78232
- return join66(homedir39(), p.slice(2));
78402
+ return join67(homedir40(), p.slice(2));
78233
78403
  return p;
78234
78404
  }
78235
78405
  async function claimWorktree(input, codeRepos) {
78236
78406
  const repoPath = resolveRepoPath(input.repo, codeRepos);
78237
- if (!existsSync66(repoPath)) {
78407
+ if (!existsSync67(repoPath)) {
78238
78408
  throw new Error(`Repository path does not exist: ${repoPath}`);
78239
78409
  }
78240
78410
  let concurrencyCap = DEFAULT_CONCURRENCY;
@@ -78257,7 +78427,7 @@ async function claimWorktree(input, codeRepos) {
78257
78427
  branch = `task/${taskSuffix}-${id}`;
78258
78428
  const baseDir = worktreesBaseDir();
78259
78429
  mkdirSync36(baseDir, { recursive: true });
78260
- worktreePath = join66(baseDir, `${id}-${taskSuffix}`);
78430
+ worktreePath = join67(baseDir, `${id}-${taskSuffix}`);
78261
78431
  const now = new Date().toISOString();
78262
78432
  const record2 = {
78263
78433
  id,
@@ -78288,7 +78458,7 @@ async function claimWorktree(input, codeRepos) {
78288
78458
 
78289
78459
  // src/worktree/release.ts
78290
78460
  import { execFileSync as execFileSync22 } from "node:child_process";
78291
- import { existsSync as existsSync67 } from "node:fs";
78461
+ import { existsSync as existsSync68 } from "node:fs";
78292
78462
  function releaseWorktree(input) {
78293
78463
  const { id } = input;
78294
78464
  const record2 = readRecord(id);
@@ -78296,7 +78466,7 @@ function releaseWorktree(input) {
78296
78466
  return { released: true };
78297
78467
  }
78298
78468
  let gitSuccess = true;
78299
- if (existsSync67(record2.path)) {
78469
+ if (existsSync68(record2.path)) {
78300
78470
  try {
78301
78471
  execFileSync22("git", ["worktree", "remove", "--force", record2.path], {
78302
78472
  cwd: record2.repo,
@@ -78335,7 +78505,7 @@ function listWorktrees() {
78335
78505
 
78336
78506
  // src/worktree/reaper.ts
78337
78507
  import { execFileSync as execFileSync23 } from "node:child_process";
78338
- import { existsSync as existsSync68 } from "node:fs";
78508
+ import { existsSync as existsSync69 } from "node:fs";
78339
78509
  var STALE_THRESHOLD_MS = 10 * 60 * 1000;
78340
78510
  function isPathInUse(path7) {
78341
78511
  try {
@@ -78362,7 +78532,7 @@ function hasUncommittedChanges(repoPath, worktreePath) {
78362
78532
  function reapRecord(record2) {
78363
78533
  const { id, path: path7, repo, branch, ownerAgent } = record2;
78364
78534
  let warning = null;
78365
- if (existsSync68(path7)) {
78535
+ if (existsSync69(path7)) {
78366
78536
  if (hasUncommittedChanges(repo, path7)) {
78367
78537
  warning = `[worktree-reaper] Reaped worktree with uncommitted changes: ` + `id=${id} branch=${branch} agent=${ownerAgent ?? "unknown"} path=${path7}`;
78368
78538
  }
@@ -78383,7 +78553,7 @@ function runReaper(nowMs) {
78383
78553
  const warnings = [];
78384
78554
  for (const record2 of records) {
78385
78555
  const heartbeatAge = now - new Date(record2.heartbeatAt).getTime();
78386
- const worktreeExists = existsSync68(record2.path);
78556
+ const worktreeExists = existsSync69(record2.path);
78387
78557
  if (!worktreeExists) {
78388
78558
  deleteRecord(record2.id);
78389
78559
  reaped.push(record2.id);
@@ -78508,11 +78678,11 @@ init_scaffold_integration();
78508
78678
  import {
78509
78679
  chmodSync as chmodSync9,
78510
78680
  mkdirSync as mkdirSync37,
78511
- readdirSync as readdirSync24,
78681
+ readdirSync as readdirSync25,
78512
78682
  rmSync as rmSync15,
78513
78683
  writeFileSync as writeFileSync32
78514
78684
  } from "node:fs";
78515
- import { join as join67 } from "node:path";
78685
+ import { join as join68 } from "node:path";
78516
78686
  function encodeCredentialsFilename(email) {
78517
78687
  const SAFE = new Set([
78518
78688
  ..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
@@ -78702,16 +78872,16 @@ function resolveCredentialsDir(env2) {
78702
78872
  if (explicit && explicit.length > 0)
78703
78873
  return explicit;
78704
78874
  const stateBase = env2.SWITCHROOM_CONTAINER === "1" ? "/state/agent" : env2.HOME ?? ".";
78705
- return join67(stateBase, "google-workspace-mcp", "credentials");
78875
+ return join68(stateBase, "google-workspace-mcp", "credentials");
78706
78876
  }
78707
78877
  function writeSeedFile(dir, email, seed) {
78708
78878
  mkdirSync37(dir, { recursive: true, mode: 448 });
78709
78879
  chmodSync9(dir, 448);
78710
- for (const name of readdirSync24(dir)) {
78711
- rmSync15(join67(dir, name), { force: true, recursive: true });
78880
+ for (const name of readdirSync25(dir)) {
78881
+ rmSync15(join68(dir, name), { force: true, recursive: true });
78712
78882
  }
78713
78883
  const filename = encodeCredentialsFilename(email);
78714
- const filePath = join67(dir, filename);
78884
+ const filePath = join68(dir, filename);
78715
78885
  writeFileSync32(filePath, JSON.stringify(seed), { mode: 384 });
78716
78886
  chmodSync9(filePath, 384);
78717
78887
  return filePath;
@@ -78871,7 +79041,7 @@ function registerDriveMcpLauncherCommand(program3) {
78871
79041
  init_scaffold_integration();
78872
79042
  import { spawn as spawn6 } from "node:child_process";
78873
79043
  import { writeFileSync as writeFileSync33, mkdirSync as mkdirSync38 } from "node:fs";
78874
- import { dirname as dirname17, join as join68 } from "node:path";
79044
+ import { dirname as dirname18, join as join69 } from "node:path";
78875
79045
  var SOFTERIA_TOKEN_ENV = "MS365_MCP_OAUTH_TOKEN";
78876
79046
  var DEFAULT_REFRESH_LEAD_MS = 5 * 60 * 1000;
78877
79047
  var MAX_REFRESH_INTERVAL_MS = 60 * 60 * 1000;
@@ -78896,14 +79066,14 @@ function computeRefreshDelayMs(expiresAt, now, leadMs = DEFAULT_REFRESH_LEAD_MS)
78896
79066
  function writeRefreshHeartbeat(agentName, data) {
78897
79067
  const path7 = heartbeatPath(agentName);
78898
79068
  try {
78899
- mkdirSync38(dirname17(path7), { recursive: true });
79069
+ mkdirSync38(dirname18(path7), { recursive: true });
78900
79070
  writeFileSync33(path7, JSON.stringify(data, null, 2), { mode: 420 });
78901
79071
  } catch {}
78902
79072
  }
78903
79073
  function heartbeatPath(agentName) {
78904
79074
  const override = process.env.SWITCHROOM_M365_HEARTBEAT_DIR;
78905
79075
  if (override) {
78906
- return join68(override, `m365-launcher-${agentName}.heartbeat.json`);
79076
+ return join69(override, `m365-launcher-${agentName}.heartbeat.json`);
78907
79077
  }
78908
79078
  return "/state/agent/m365-launcher.heartbeat.json";
78909
79079
  }
@@ -79088,8 +79258,8 @@ function registerM365McpLauncherCommand(program3) {
79088
79258
  // src/cli/notion-mcp-launcher.ts
79089
79259
  init_scaffold_integration();
79090
79260
  import { spawn as spawn7 } from "node:child_process";
79091
- import { existsSync as existsSync69, mkdirSync as mkdirSync39, writeFileSync as writeFileSync34 } from "node:fs";
79092
- import { dirname as dirname18 } from "node:path";
79261
+ import { existsSync as existsSync70, mkdirSync as mkdirSync39, writeFileSync as writeFileSync34 } from "node:fs";
79262
+ import { dirname as dirname19 } from "node:path";
79093
79263
  var HEARTBEAT_WRITE_INTERVAL_MS = 30 * 1000;
79094
79264
  var DEFAULT_HEARTBEAT_PATH = "/state/agent/notion-launcher.heartbeat.json";
79095
79265
  var DEFAULT_VAULT_KEY = "notion/integration-token";
@@ -79099,8 +79269,8 @@ function buildNotionMcpArgs(opts) {
79099
79269
  }
79100
79270
  function defaultWriteHeartbeat(path7, contents) {
79101
79271
  try {
79102
- const dir = dirname18(path7);
79103
- if (!existsSync69(dir))
79272
+ const dir = dirname19(path7);
79273
+ if (!existsSync70(dir))
79104
79274
  mkdirSync39(dir, { recursive: true });
79105
79275
  writeFileSync34(path7, contents);
79106
79276
  } catch {}
@@ -79212,7 +79382,7 @@ function registerNotionMcpLauncherCommand(program3) {
79212
79382
 
79213
79383
  // src/cli/deliver-file.ts
79214
79384
  init_client2();
79215
- import { readFileSync as readFileSync58, statSync as statSync28 } from "node:fs";
79385
+ import { readFileSync as readFileSync58, statSync as statSync29 } from "node:fs";
79216
79386
  import { basename as basename7 } from "node:path";
79217
79387
 
79218
79388
  // src/delivery/onedrive.ts
@@ -79502,7 +79672,7 @@ async function defaultResolveProvider() {
79502
79672
  }
79503
79673
  async function runDeliverFile(localPath, deps = {}) {
79504
79674
  const agentName = safeAgentName(deps.agentName ?? process.env.SWITCHROOM_AGENT_NAME);
79505
- const sizeOf = deps.fileSize ?? ((p) => statSync28(p).size);
79675
+ const sizeOf = deps.fileSize ?? ((p) => statSync29(p).size);
79506
79676
  const read = deps.readFile ?? ((p) => new Uint8Array(readFileSync58(p)));
79507
79677
  const resolveProvider = deps.resolveProvider ?? defaultResolveProvider;
79508
79678
  let size;
@@ -79793,8 +79963,8 @@ async function fetchToken(vaultKey) {
79793
79963
 
79794
79964
  // src/cli/apply.ts
79795
79965
  init_source();
79796
- import { accessSync as accessSync3, chownSync as chownSync4, constants as fsConstants6, copyFileSync as copyFileSync11, existsSync as existsSync73, mkdirSync as mkdirSync41, readFileSync as readFileSync60, readdirSync as readdirSync26, renameSync as renameSync14, writeFileSync as writeFileSync36 } from "node:fs";
79797
- import { mkdir, writeFile } from "node:fs/promises";
79966
+ import { accessSync as accessSync3, chownSync as chownSync5, constants as fsConstants6, copyFileSync as copyFileSync11, existsSync as existsSync73, mkdirSync as mkdirSync41, readFileSync as readFileSync60, readdirSync as readdirSync26, renameSync as renameSync14, writeFileSync as writeFileSync36 } from "node:fs";
79967
+ import { mkdir as mkdir2 } from "node:fs/promises";
79798
79968
  import { spawnSync as childSpawnSync } from "node:child_process";
79799
79969
  import readline from "node:readline";
79800
79970
 
@@ -80182,16 +80352,16 @@ agents:
80182
80352
 
80183
80353
  // src/cli/apply.ts
80184
80354
  init_resolver();
80185
- import { dirname as dirname21, join as join72, resolve as resolve44 } from "node:path";
80186
- import { homedir as homedir41 } from "node:os";
80355
+ import { dirname as dirname22, join as join72, resolve as resolve44 } from "node:path";
80356
+ import { homedir as homedir42 } from "node:os";
80187
80357
  import { execFileSync as execFileSync24 } from "node:child_process";
80188
80358
  init_vault();
80189
80359
  init_loader();
80190
80360
  init_loader();
80191
80361
 
80192
80362
  // src/cli/update-prompt-hook.ts
80193
- import { existsSync as existsSync70, readFileSync as readFileSync59, writeFileSync as writeFileSync35, chmodSync as chmodSync10, mkdirSync as mkdirSync40 } from "node:fs";
80194
- import { join as join69 } from "node:path";
80363
+ import { existsSync as existsSync71, readFileSync as readFileSync59, writeFileSync as writeFileSync35, chmodSync as chmodSync10, mkdirSync as mkdirSync40 } from "node:fs";
80364
+ import { join as join70 } from "node:path";
80195
80365
  var HOOK_FILENAME = "update-card-on-prompt.sh";
80196
80366
  function updatePromptHookScript() {
80197
80367
  return `#!/bin/bash
@@ -80257,12 +80427,12 @@ exit 0
80257
80427
  `;
80258
80428
  }
80259
80429
  function installUpdatePromptHook(agentDir) {
80260
- const hooksDir = join69(agentDir, ".claude", "hooks");
80430
+ const hooksDir = join70(agentDir, ".claude", "hooks");
80261
80431
  mkdirSync40(hooksDir, { recursive: true });
80262
- const scriptPath = join69(hooksDir, HOOK_FILENAME);
80432
+ const scriptPath = join70(hooksDir, HOOK_FILENAME);
80263
80433
  const desired = updatePromptHookScript();
80264
80434
  let installed = false;
80265
- const existing = existsSync70(scriptPath) ? readFileSync59(scriptPath, "utf-8") : "";
80435
+ const existing = existsSync71(scriptPath) ? readFileSync59(scriptPath, "utf-8") : "";
80266
80436
  if (existing !== desired) {
80267
80437
  writeFileSync35(scriptPath, desired, { mode: 493 });
80268
80438
  chmodSync10(scriptPath, 493);
@@ -80272,8 +80442,8 @@ function installUpdatePromptHook(agentDir) {
80272
80442
  chmodSync10(scriptPath, 493);
80273
80443
  } catch {}
80274
80444
  }
80275
- const settingsPath = join69(agentDir, ".claude", "settings.json");
80276
- if (!existsSync70(settingsPath)) {
80445
+ const settingsPath = join70(agentDir, ".claude", "settings.json");
80446
+ if (!existsSync71(settingsPath)) {
80277
80447
  return { scriptPath, settingsPath, installed };
80278
80448
  }
80279
80449
  const raw = readFileSync59(settingsPath, "utf-8");
@@ -80319,26 +80489,6 @@ function installUpdatePromptHook(agentDir) {
80319
80489
  // src/cli/apply.ts
80320
80490
  init_compose();
80321
80491
 
80322
- // src/config/release-resolve.ts
80323
- function resolveImageTag(release) {
80324
- if (!release)
80325
- return "latest";
80326
- if (release.pin)
80327
- return release.pin;
80328
- if (release.channel)
80329
- return release.channel;
80330
- return "latest";
80331
- }
80332
- function resolveRelease(opts) {
80333
- if (opts.override)
80334
- return opts.override;
80335
- if (opts.perAgent)
80336
- return opts.perAgent;
80337
- if (opts.root)
80338
- return opts.root;
80339
- return;
80340
- }
80341
-
80342
80492
  // src/cli/install-detect.ts
80343
80493
  import * as fs4 from "node:fs";
80344
80494
  import * as path7 from "node:path";
@@ -80389,107 +80539,17 @@ function detectInstallType() {
80389
80539
  }
80390
80540
  }
80391
80541
 
80392
- // src/cli/operator-uid.ts
80393
- import {
80394
- chownSync as chownSync3,
80395
- existsSync as existsSync72,
80396
- lstatSync as lstatSync7,
80397
- readdirSync as readdirSync25,
80398
- realpathSync as realpathSync6,
80399
- statSync as statSync29
80400
- } from "node:fs";
80401
- import { join as join71 } from "node:path";
80402
- function resolveOperatorUid() {
80403
- const sudoUid = process.env.SUDO_UID;
80404
- if (sudoUid !== undefined) {
80405
- const parsed = parseInt(sudoUid, 10);
80406
- if (Number.isFinite(parsed) && parsed > 0)
80407
- return parsed;
80408
- }
80409
- if (typeof process.getuid === "function") {
80410
- const uid = process.getuid();
80411
- if (uid > 0)
80412
- return uid;
80413
- }
80414
- return;
80415
- }
80416
- function operatorOwnedPaths(home2) {
80417
- const root = join71(home2, ".switchroom");
80418
- return [
80419
- join71(root, "vault"),
80420
- join71(root, "vault-auto-unlock"),
80421
- join71(root, "vault-audit.log"),
80422
- join71(root, "host-control-audit.log"),
80423
- join71(root, "accounts"),
80424
- join71(root, "compose")
80425
- ];
80426
- }
80427
- function restoreOperatorOwnership(home2, operatorUid, deps = {}) {
80428
- const chown = deps.chown ?? ((p, u, g) => chownSync3(p, u, g));
80429
- const exists = deps.exists ?? ((p) => existsSync72(p));
80430
- const isSymlink = deps.isSymlink ?? ((p) => {
80431
- try {
80432
- return lstatSync7(p).isSymbolicLink();
80433
- } catch {
80434
- return false;
80435
- }
80436
- });
80437
- const isDir = deps.isDir ?? ((p) => {
80438
- try {
80439
- return statSync29(p).isDirectory();
80440
- } catch {
80441
- return false;
80442
- }
80443
- });
80444
- const realpath2 = deps.realpath ?? ((p) => {
80445
- try {
80446
- return realpathSync6(p);
80447
- } catch {
80448
- return p;
80449
- }
80450
- });
80451
- const readdir2 = deps.readdir ?? ((p) => {
80452
- try {
80453
- return readdirSync25(p);
80454
- } catch {
80455
- return [];
80456
- }
80457
- });
80458
- const chowned = [];
80459
- const seen = new Set;
80460
- const visit = (path8) => {
80461
- if (!exists(path8))
80462
- return;
80463
- const target = isSymlink(path8) ? realpath2(path8) : path8;
80464
- if (seen.has(target))
80465
- return;
80466
- seen.add(target);
80467
- try {
80468
- chown(target, operatorUid, operatorUid);
80469
- chowned.push(target);
80470
- } catch {}
80471
- if (isDir(target)) {
80472
- for (const entry of readdir2(target)) {
80473
- visit(join71(target, entry));
80474
- }
80475
- }
80476
- };
80477
- for (const p of operatorOwnedPaths(home2))
80478
- visit(p);
80479
- return chowned;
80480
- }
80481
-
80482
80542
  // src/cli/apply.ts
80483
80543
  var EMBEDDED_EXAMPLES = {
80484
80544
  switchroom: switchroom_default,
80485
80545
  minimal: minimal_default
80486
80546
  };
80487
- var DEFAULT_COMPOSE_PATH2 = join72(homedir41(), ".switchroom", "compose", "docker-compose.yml");
80547
+ var DEFAULT_COMPOSE_PATH2 = join72(homedir42(), ".switchroom", "compose", "docker-compose.yml");
80488
80548
  var COMPOSE_PROJECT2 = "switchroom";
80489
80549
  function resolveVaultBindMountDir(homeDir, ctx) {
80490
80550
  const isCustomPath = ctx.migrationKind === "custom-path-skipped";
80491
80551
  if (isCustomPath && ctx.customVaultPath) {
80492
- return dirname21(ctx.customVaultPath);
80552
+ return dirname22(ctx.customVaultPath);
80493
80553
  }
80494
80554
  return join72(homeDir, ".switchroom", "vault");
80495
80555
  }
@@ -80520,7 +80580,7 @@ function hasVaultRefs(value) {
80520
80580
  return false;
80521
80581
  }
80522
80582
  async function ensureHostMountSources(config) {
80523
- const home2 = homedir41();
80583
+ const home2 = homedir42();
80524
80584
  const dirs = [
80525
80585
  join72(home2, ".switchroom", "approvals"),
80526
80586
  join72(home2, ".switchroom", "scheduler"),
@@ -80538,7 +80598,7 @@ async function ensureHostMountSources(config) {
80538
80598
  }
80539
80599
  }
80540
80600
  for (const dir of dirs) {
80541
- await mkdir(dir, { recursive: true });
80601
+ await mkdir2(dir, { recursive: true });
80542
80602
  }
80543
80603
  const autoUnlockPath = join72(home2, ".switchroom", "vault-auto-unlock");
80544
80604
  if (!existsSync73(autoUnlockPath)) {
@@ -80563,11 +80623,11 @@ async function ensureHostMountSources(config) {
80563
80623
  }
80564
80624
  try {
80565
80625
  const uid = allocateAgentUid(name);
80566
- chownSync4(tokenPath, uid, uid);
80626
+ chownSync5(tokenPath, uid, uid);
80567
80627
  } catch {}
80568
80628
  }
80569
80629
  const fleetDir = join72(home2, ".switchroom", "fleet");
80570
- await mkdir(fleetDir, { recursive: true });
80630
+ await mkdir2(fleetDir, { recursive: true });
80571
80631
  const invariantsPath = join72(fleetDir, "switchroom-invariants.md");
80572
80632
  const invariantsCanonical = renderFleetInvariants();
80573
80633
  const invariantsCurrent = existsSync73(invariantsPath) ? readFileSync60(invariantsPath, "utf-8") : null;
@@ -80657,7 +80717,7 @@ function detectAndReportLegacyGdriveSlots(vaultPath) {
80657
80717
  `));
80658
80718
  }
80659
80719
  }
80660
- function writeInstallTypeCache(homeDir = homedir41()) {
80720
+ function writeInstallTypeCache(homeDir = homedir42()) {
80661
80721
  const ctx = detectInstallType();
80662
80722
  const dir = join72(homeDir, ".switchroom");
80663
80723
  const out = join72(dir, "install-type.json");
@@ -80767,7 +80827,7 @@ Applying switchroom config...
80767
80827
  }
80768
80828
  const vaultPathConfigured = config.vault?.path;
80769
80829
  const customVaultPath = vaultPathConfigured ? resolvePath(vaultPathConfigured) : undefined;
80770
- const migrationResult = migrateVaultLayout(homedir41(), {
80830
+ const migrationResult = migrateVaultLayout(homedir42(), {
80771
80831
  customVaultPath
80772
80832
  });
80773
80833
  switch (migrationResult.kind) {
@@ -80793,7 +80853,7 @@ Applying switchroom config...
80793
80853
  writeErr(formatDivergentRecoveryMessage(migrationResult.details));
80794
80854
  process.exit(4);
80795
80855
  }
80796
- const postMigrationInspect = inspectVaultLayout(homedir41());
80856
+ const postMigrationInspect = inspectVaultLayout(homedir42());
80797
80857
  const acceptable = [
80798
80858
  "no-vault",
80799
80859
  "already-migrated",
@@ -80808,7 +80868,7 @@ Applying switchroom config...
80808
80868
  `));
80809
80869
  process.exit(5);
80810
80870
  }
80811
- const vaultDir = resolveVaultBindMountDir(homedir41(), {
80871
+ const vaultDir = resolveVaultBindMountDir(homedir42(), {
80812
80872
  migrationKind: migrationResult.kind,
80813
80873
  customVaultPath
80814
80874
  });
@@ -80828,26 +80888,14 @@ Applying switchroom config...
80828
80888
  }
80829
80889
  const composePath = options.outPath ?? DEFAULT_COMPOSE_PATH2;
80830
80890
  const operatorUid = resolveOperatorUid();
80831
- const composeRelease = resolveRelease({
80832
- override: options.releaseOverride,
80833
- root: config.release
80834
- });
80835
- const composeImageTag = resolveImageTag(composeRelease);
80836
- const composeContent = generateCompose({
80891
+ const { bytes: composeBytes } = await writeComposeFile({
80837
80892
  config,
80838
- imageTag: composeImageTag,
80839
- buildMode: options.buildLocal ? "local" : "pull",
80840
- buildContext: options.buildContext,
80841
- homeDir: homedir41(),
80893
+ composePath,
80842
80894
  switchroomConfigPath,
80843
- operatorUid
80844
- });
80845
- await mkdir(dirname21(composePath), { recursive: true });
80846
- await writeFile(composePath, composeContent, {
80847
- encoding: "utf8",
80848
- mode: 384
80895
+ releaseOverride: options.releaseOverride,
80896
+ buildMode: options.buildLocal ? "local" : "pull",
80897
+ buildContext: options.buildContext
80849
80898
  });
80850
- const composeBytes = Buffer.byteLength(composeContent, "utf8");
80851
80899
  writeOut(source_default.bold(`
80852
80900
  Wrote `) + composePath + source_default.gray(` (${composeBytes} bytes)
80853
80901
  `));
@@ -80858,7 +80906,7 @@ Wrote `) + composePath + source_default.gray(` (${composeBytes} bytes)
80858
80906
  writeOut(source_default.gray(` (If pull returns 401, login to ghcr.io first: see docs/operators/install.md#ghcr-auth)
80859
80907
  `));
80860
80908
  if (process.geteuid?.() === 0 && operatorUid !== undefined) {
80861
- const restored = restoreOperatorOwnership(homedir41(), operatorUid);
80909
+ const restored = restoreOperatorOwnership(homedir42(), operatorUid);
80862
80910
  if (restored.length > 0) {
80863
80911
  writeOut(source_default.gray(` Restored operator ownership of ${restored.length} ~/.switchroom path(s)
80864
80912
  `));
@@ -81109,7 +81157,7 @@ function runRedactStdin() {
81109
81157
  // src/cli/status-ask.ts
81110
81158
  import { readFileSync as readFileSync61, existsSync as existsSync74, readdirSync as readdirSync27 } from "node:fs";
81111
81159
  import { join as join73 } from "node:path";
81112
- import { homedir as homedir42 } from "node:os";
81160
+ import { homedir as homedir43 } from "node:os";
81113
81161
 
81114
81162
  // src/status-ask/report.ts
81115
81163
  function parseJsonl(content) {
@@ -81444,7 +81492,7 @@ function resolveSources(explicitPath) {
81444
81492
  const config = loadConfig();
81445
81493
  agentsDir = resolveAgentsDir(config);
81446
81494
  } catch {
81447
- agentsDir = join73(homedir42(), ".switchroom", "agents");
81495
+ agentsDir = join73(homedir43(), ".switchroom", "agents");
81448
81496
  }
81449
81497
  if (!existsSync74(agentsDir))
81450
81498
  return [];
@@ -81479,14 +81527,14 @@ function inferAgentFromPath(p) {
81479
81527
  // src/cli/agent-config.ts
81480
81528
  init_helpers();
81481
81529
  import { join as join74 } from "node:path";
81482
- import { homedir as homedir43 } from "node:os";
81530
+ import { homedir as homedir44 } from "node:os";
81483
81531
  import {
81484
81532
  existsSync as existsSync75,
81485
81533
  mkdirSync as mkdirSync42,
81486
81534
  appendFileSync as appendFileSync4,
81487
81535
  readFileSync as readFileSync62
81488
81536
  } from "node:fs";
81489
- var AUDIT_ROOT = join74(homedir43(), ".switchroom", "audit");
81537
+ var AUDIT_ROOT = join74(homedir44(), ".switchroom", "audit");
81490
81538
  function auditPathFor(agent) {
81491
81539
  return join74(AUDIT_ROOT, agent, "agent-config.jsonl");
81492
81540
  }
@@ -82986,8 +83034,8 @@ import {
82986
83034
  statSync as statSync31,
82987
83035
  writeFileSync as writeFileSync38
82988
83036
  } from "node:fs";
82989
- import { tmpdir as tmpdir5, homedir as homedir44 } from "node:os";
82990
- import { dirname as dirname22, join as join78, relative as relative2, resolve as resolve46 } from "node:path";
83037
+ import { tmpdir as tmpdir5, homedir as homedir45 } from "node:os";
83038
+ import { dirname as dirname23, join as join78, relative as relative2, resolve as resolve46 } from "node:path";
82991
83039
  import { spawnSync as spawnSync11 } from "node:child_process";
82992
83040
 
82993
83041
  // src/cli/skill-common.ts
@@ -83181,10 +83229,10 @@ function scanForClaudeP2(content) {
83181
83229
  function resolveSkillsPoolDir2(override) {
83182
83230
  const raw = override ?? "~/.switchroom/skills";
83183
83231
  if (raw.startsWith("~/")) {
83184
- return join78(homedir44(), raw.slice(2));
83232
+ return join78(homedir45(), raw.slice(2));
83185
83233
  }
83186
83234
  if (raw === "~")
83187
- return homedir44();
83235
+ return homedir45();
83188
83236
  return resolve46(raw);
83189
83237
  }
83190
83238
  function readStdinSync() {
@@ -83417,7 +83465,7 @@ function writePayload(poolDir, name, files) {
83417
83465
  try {
83418
83466
  for (const [path8, content] of Object.entries(files)) {
83419
83467
  const full = join78(staging, path8);
83420
- mkdirSync45(dirname22(full), { recursive: true, mode: 493 });
83468
+ mkdirSync45(dirname23(full), { recursive: true, mode: 493 });
83421
83469
  const fd = openSync15(full, "wx");
83422
83470
  try {
83423
83471
  writeFileSync38(fd, content);
@@ -83538,8 +83586,8 @@ import {
83538
83586
  utimesSync,
83539
83587
  writeFileSync as writeFileSync39
83540
83588
  } from "node:fs";
83541
- import { dirname as dirname23, join as join79, relative as relative3, resolve as resolve47 } from "node:path";
83542
- import { homedir as homedir45, tmpdir as tmpdir6 } from "node:os";
83589
+ import { dirname as dirname24, join as join79, relative as relative3, resolve as resolve47 } from "node:path";
83590
+ import { homedir as homedir46, tmpdir as tmpdir6 } from "node:os";
83543
83591
  import { spawnSync as spawnSync12 } from "node:child_process";
83544
83592
  init_helpers();
83545
83593
  init_source();
@@ -83549,7 +83597,7 @@ var TRASH_TTL_MS = 24 * 60 * 60 * 1000;
83549
83597
  var PERSONAL_SKILLS_SUBPATH = "personal-skills";
83550
83598
  function resolveConfigSkillsDir(agent) {
83551
83599
  const override = process.env.SWITCHROOM_CONFIG_DIR;
83552
- const candidate = override ? resolve47(override) : join79(homedir45(), ".switchroom-config");
83600
+ const candidate = override ? resolve47(override) : join79(homedir46(), ".switchroom-config");
83553
83601
  if (!existsSync81(candidate))
83554
83602
  return null;
83555
83603
  return join79(candidate, "agents", agent, PERSONAL_SKILLS_SUBPATH);
@@ -83645,7 +83693,7 @@ function resolveAgent(opts) {
83645
83693
  function resolveAgentsRoot(opts) {
83646
83694
  if (opts.root)
83647
83695
  return resolve47(opts.root);
83648
- return join79(homedir45(), ".switchroom", "agents");
83696
+ return join79(homedir46(), ".switchroom", "agents");
83649
83697
  }
83650
83698
  function personalSkillDir(agentsRoot, agent, name) {
83651
83699
  return join79(agentsRoot, agent, ".claude", "skills", PERSONAL_PREFIX + name);
@@ -83779,13 +83827,13 @@ function writePersonalSkill(targetDir, files) {
83779
83827
  if (targetIsSymlink) {
83780
83828
  fail3(`refusing to overwrite symlink at ${targetDir}; investigate manually`);
83781
83829
  }
83782
- mkdirSync46(dirname23(targetDir), { recursive: true, mode: 493 });
83783
- const staging = mkdtempSync6(join79(dirname23(targetDir), `.skill-personal-stage-`));
83830
+ mkdirSync46(dirname24(targetDir), { recursive: true, mode: 493 });
83831
+ const staging = mkdtempSync6(join79(dirname24(targetDir), `.skill-personal-stage-`));
83784
83832
  let oldRename = null;
83785
83833
  try {
83786
83834
  for (const [path8, content] of Object.entries(files)) {
83787
83835
  const full = join79(staging, path8);
83788
- mkdirSync46(dirname23(full), { recursive: true, mode: 493 });
83836
+ mkdirSync46(dirname24(full), { recursive: true, mode: 493 });
83789
83837
  const fd = openSync16(full, "wx");
83790
83838
  try {
83791
83839
  writeFileSync39(fd, content);
@@ -83917,10 +83965,10 @@ function editPersonalAction(name, opts) {
83917
83965
  }
83918
83966
  var CLONE_SOURCE_RE = /^(shared|bundled):([a-z0-9][a-z0-9_-]{0,62})$/;
83919
83967
  function defaultSharedRoot() {
83920
- return join79(homedir45(), ".switchroom", "skills");
83968
+ return join79(homedir46(), ".switchroom", "skills");
83921
83969
  }
83922
83970
  function defaultBundledRoot() {
83923
- return join79(homedir45(), ".switchroom", "skills", "_bundled");
83971
+ return join79(homedir46(), ".switchroom", "skills", "_bundled");
83924
83972
  }
83925
83973
  function resolveCloneSource(source, opts) {
83926
83974
  const m = CLONE_SOURCE_RE.exec(source);
@@ -84136,19 +84184,19 @@ function registerSkillPersonalCommands(program3) {
84136
84184
  init_helpers();
84137
84185
  var import_yaml23 = __toESM(require_dist(), 1);
84138
84186
  import { existsSync as existsSync82, readdirSync as readdirSync32, readFileSync as readFileSync68, statSync as statSync33 } from "node:fs";
84139
- import { homedir as homedir46 } from "node:os";
84187
+ import { homedir as homedir47 } from "node:os";
84140
84188
  import { join as join80, resolve as resolve48 } from "node:path";
84141
84189
  var PERSONAL_PREFIX2 = "personal-";
84142
84190
  var BUNDLED_SUBDIR = "_bundled";
84143
84191
  var AGENT_NAME_RE3 = /^[a-z][a-z0-9_-]{0,62}$/;
84144
84192
  function defaultAgentsRoot() {
84145
- return resolve48(homedir46(), ".switchroom/agents");
84193
+ return resolve48(homedir47(), ".switchroom/agents");
84146
84194
  }
84147
84195
  function defaultSharedRoot2() {
84148
- return resolve48(homedir46(), ".switchroom/skills");
84196
+ return resolve48(homedir47(), ".switchroom/skills");
84149
84197
  }
84150
84198
  function defaultBundledRoot2() {
84151
- return resolve48(homedir46(), ".switchroom/skills/_bundled");
84199
+ return resolve48(homedir47(), ".switchroom/skills/_bundled");
84152
84200
  }
84153
84201
  function readSkillFrontmatter(skillDir) {
84154
84202
  const mdPath = join80(skillDir, "SKILL.md");
@@ -84429,7 +84477,7 @@ function registerHostdMcpCommand(program3) {
84429
84477
  init_source();
84430
84478
  init_helpers();
84431
84479
  import { existsSync as existsSync84, mkdirSync as mkdirSync47, readdirSync as readdirSync33, readFileSync as readFileSync70, writeFileSync as writeFileSync40, statSync as statSync34, copyFileSync as copyFileSync12 } from "node:fs";
84432
- import { homedir as homedir47 } from "node:os";
84480
+ import { homedir as homedir48 } from "node:os";
84433
84481
  import { join as join81 } from "node:path";
84434
84482
  import { spawnSync as spawnSync14 } from "node:child_process";
84435
84483
  init_audit_reader();
@@ -84521,7 +84569,7 @@ networks:
84521
84569
  `;
84522
84570
  }
84523
84571
  function hostdDir() {
84524
- return join81(homedir47(), ".switchroom", "hostd");
84572
+ return join81(homedir48(), ".switchroom", "hostd");
84525
84573
  }
84526
84574
  function hostdComposePath() {
84527
84575
  return join81(hostdDir(), "docker-compose.yml");
@@ -84563,7 +84611,7 @@ async function doInstall(opts, program3) {
84563
84611
  const composePath = hostdComposePath();
84564
84612
  mkdirSync47(dir, { recursive: true });
84565
84613
  const yaml = renderHostdComposeFile({
84566
- hostHome: homedir47(),
84614
+ hostHome: homedir48(),
84567
84615
  imageTag: opts.tag ?? DEFAULT_IMAGE_TAG,
84568
84616
  operatorUid: resolveOperatorUid()
84569
84617
  });
@@ -84726,7 +84774,7 @@ The log is created when hostd handles its first privileged-verb request.`));
84726
84774
  init_source();
84727
84775
  init_helpers();
84728
84776
  import { existsSync as existsSync85, mkdirSync as mkdirSync48, writeFileSync as writeFileSync41, copyFileSync as copyFileSync13 } from "node:fs";
84729
- import { homedir as homedir48 } from "node:os";
84777
+ import { homedir as homedir49 } from "node:os";
84730
84778
  import { join as join82 } from "node:path";
84731
84779
  import { spawnSync as spawnSync15 } from "node:child_process";
84732
84780
  var DEFAULT_IMAGE_TAG2 = "latest";
@@ -84808,7 +84856,7 @@ services:
84808
84856
  `;
84809
84857
  }
84810
84858
  function webdDir() {
84811
- return join82(homedir48(), ".switchroom", "web");
84859
+ return join82(homedir49(), ".switchroom", "web");
84812
84860
  }
84813
84861
  function webdComposePath() {
84814
84862
  return join82(webdDir(), "docker-compose.yml");
@@ -84842,7 +84890,7 @@ async function doInstall2(opts) {
84842
84890
  const composePath = webdComposePath();
84843
84891
  mkdirSync48(dir, { recursive: true });
84844
84892
  const yaml = renderWebComposeFile({
84845
- hostHome: homedir48(),
84893
+ hostHome: homedir49(),
84846
84894
  imageTag: opts.tag ?? DEFAULT_IMAGE_TAG2,
84847
84895
  operatorUid
84848
84896
  });