switchroom 0.14.66 → 0.14.67

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.
@@ -23623,7 +23623,7 @@ function bringUpAgentService(opts) {
23623
23623
  writeFileSync6(composePath, compose, { mode: 384 });
23624
23624
  const dockerBin = opts.dockerBin ?? "docker";
23625
23625
  const stdio = opts.stdio ?? "inherit";
23626
- for (const svc of ["vault-broker", "approval-kernel"]) {
23626
+ for (const svc of ["vault-broker", "approval-kernel", "switchroom-auth-broker"]) {
23627
23627
  execFileSync6(dockerBin, [
23628
23628
  "compose",
23629
23629
  "-f",
@@ -23651,9 +23651,93 @@ var init_docker_fleet = __esm(() => {
23651
23651
  init_loader();
23652
23652
  });
23653
23653
 
23654
+ // src/agents/singleton-reconcile.ts
23655
+ import { execFileSync as execFileSync7 } from "node:child_process";
23656
+ import { readFileSync as readFileSync13 } from "node:fs";
23657
+ function singletonContainerName(svc) {
23658
+ return svc.startsWith("switchroom-") ? svc : `switchroom-${svc}`;
23659
+ }
23660
+ function readPinnedSingletonImages(composeText) {
23661
+ let doc;
23662
+ try {
23663
+ doc = import_yaml3.parse(composeText);
23664
+ } catch {
23665
+ return {};
23666
+ }
23667
+ const out = {};
23668
+ for (const svc of SINGLETON_SERVICES) {
23669
+ const img = doc?.services?.[svc]?.image;
23670
+ if (typeof img === "string" && img.length > 0)
23671
+ out[svc] = img;
23672
+ }
23673
+ return out;
23674
+ }
23675
+ function defaultInspectImage(dockerBin, container) {
23676
+ try {
23677
+ const out = execFileSync7(dockerBin, ["inspect", "-f", "{{.Config.Image}}", container], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"], timeout: 5000 }).trim();
23678
+ return out.length > 0 ? out : null;
23679
+ } catch {
23680
+ return null;
23681
+ }
23682
+ }
23683
+ function detectSingletonDrift(deps) {
23684
+ const dockerBin = deps.dockerBin ?? "docker";
23685
+ const readCompose = deps.readCompose ?? ((p) => readFileSync13(p, "utf-8"));
23686
+ const inspectImage = deps.inspectImage ?? ((c) => defaultInspectImage(dockerBin, c));
23687
+ let pinned = {};
23688
+ try {
23689
+ pinned = readPinnedSingletonImages(readCompose(deps.composeFile));
23690
+ } catch {
23691
+ pinned = {};
23692
+ }
23693
+ return SINGLETON_SERVICES.map((service) => {
23694
+ const container = singletonContainerName(service);
23695
+ const running = inspectImage(container);
23696
+ const pin = pinned[service] ?? null;
23697
+ const needsRecreate = pin !== null && running !== pin;
23698
+ return { service, container, running, pinned: pin, needsRecreate };
23699
+ });
23700
+ }
23701
+ function defaultRecreate(dockerBin, project, composeFile, service) {
23702
+ execFileSync7(dockerBin, ["compose", "-p", project, "-f", composeFile, "up", "-d", "--no-deps", service], { stdio: ["ignore", "pipe", "pipe"], timeout: 120000 });
23703
+ }
23704
+ function reconcileSingletons(deps) {
23705
+ const dockerBin = deps.dockerBin ?? "docker";
23706
+ const project = deps.project ?? "switchroom";
23707
+ const log = deps.log ?? ((m) => process.stderr.write(m + `
23708
+ `));
23709
+ const recreate = deps.recreate ?? ((svc) => defaultRecreate(dockerBin, project, deps.composeFile, svc));
23710
+ const drift = detectSingletonDrift(deps);
23711
+ const recreated = [];
23712
+ const failed = [];
23713
+ for (const d of drift) {
23714
+ if (!d.needsRecreate)
23715
+ continue;
23716
+ log(`singleton-reconcile: ${d.service} drift ${d.running ?? "<absent>"} \u2192 ${d.pinned} \u2014 recreating`);
23717
+ try {
23718
+ recreate(d.service);
23719
+ recreated.push(d.service);
23720
+ } catch (err) {
23721
+ const msg = err instanceof Error ? err.message : String(err);
23722
+ log(`singleton-reconcile: ${d.service} recreate FAILED: ${msg}`);
23723
+ failed.push({ service: d.service, error: msg });
23724
+ }
23725
+ }
23726
+ return { drift, recreated, failed };
23727
+ }
23728
+ var import_yaml3, SINGLETON_SERVICES;
23729
+ var init_singleton_reconcile = __esm(() => {
23730
+ import_yaml3 = __toESM(require_dist(), 1);
23731
+ SINGLETON_SERVICES = [
23732
+ "vault-broker",
23733
+ "approval-kernel",
23734
+ "switchroom-auth-broker"
23735
+ ];
23736
+ });
23737
+
23654
23738
  // src/agents/lifecycle.ts
23655
- import { execFileSync as execFileSync7, spawn, spawnSync } from "node:child_process";
23656
- import { existsSync as existsSync15, mkdirSync as mkdirSync12, writeFileSync as writeFileSync7, renameSync as renameSync4, readFileSync as readFileSync13 } from "node:fs";
23739
+ import { execFileSync as execFileSync8, spawn, spawnSync } from "node:child_process";
23740
+ import { existsSync as existsSync15, mkdirSync as mkdirSync12, writeFileSync as writeFileSync7, renameSync as renameSync4, readFileSync as readFileSync14 } from "node:fs";
23657
23741
  import { resolve as resolve13, join as join10 } from "node:path";
23658
23742
  import { connect } from "node:net";
23659
23743
  function cleanShutdownMarkerPathForAgent(name) {
@@ -23666,7 +23750,7 @@ function writeRestartReasonMarker(name, reason, opts = {}) {
23666
23750
  mkdirSync12(join10(path, ".."), { recursive: true });
23667
23751
  if (opts.preserveExisting && existsSync15(path)) {
23668
23752
  try {
23669
- const prev = JSON.parse(readFileSync13(path, "utf-8"));
23753
+ const prev = JSON.parse(readFileSync14(path, "utf-8"));
23670
23754
  if (prev && typeof prev.ts === "number" && Date.now() - prev.ts < 30000 && prev.reason) {
23671
23755
  return;
23672
23756
  }
@@ -23683,7 +23767,7 @@ function buildCliRestartReason(opts) {
23683
23767
  if (!buildCommit)
23684
23768
  return "cli: restart";
23685
23769
  try {
23686
- const head = execFileSync7("git", ["rev-parse", "HEAD"], {
23770
+ const head = execFileSync8("git", ["rev-parse", "HEAD"], {
23687
23771
  cwd: cwd ?? process.cwd(),
23688
23772
  encoding: "utf-8",
23689
23773
  stdio: ["ignore", "pipe", "ignore"]
@@ -23694,7 +23778,7 @@ function buildCliRestartReason(opts) {
23694
23778
  return "cli: restart";
23695
23779
  let subject = "";
23696
23780
  try {
23697
- subject = execFileSync7("git", ["log", "-1", "--pretty=%s", head], {
23781
+ subject = execFileSync8("git", ["log", "-1", "--pretty=%s", head], {
23698
23782
  cwd: cwd ?? process.cwd(),
23699
23783
  encoding: "utf-8",
23700
23784
  stdio: ["ignore", "pipe", "ignore"]
@@ -23719,9 +23803,12 @@ function composeFilePath() {
23719
23803
  return override;
23720
23804
  return resolve13(resolveSwitchroomHome(), "compose", "docker-compose.yml");
23721
23805
  }
23806
+ function reconcileSingletonImages(log) {
23807
+ return reconcileSingletons({ composeFile: composeFilePath(), log });
23808
+ }
23722
23809
  function dockerSync(args) {
23723
23810
  try {
23724
- return execFileSync7("docker", args, {
23811
+ return execFileSync8("docker", args, {
23725
23812
  encoding: "utf-8",
23726
23813
  stdio: ["ignore", "pipe", "pipe"]
23727
23814
  }).trim();
@@ -24103,15 +24190,16 @@ var init_lifecycle = __esm(() => {
24103
24190
  init_loader();
24104
24191
  init_tmux();
24105
24192
  init_docker_fleet();
24193
+ init_singleton_reconcile();
24106
24194
  });
24107
24195
 
24108
24196
  // src/auth/pane-ready-probe.ts
24109
- import { execFileSync as execFileSync9 } from "node:child_process";
24197
+ import { execFileSync as execFileSync10 } from "node:child_process";
24110
24198
  function defaultPaneReadyDeps() {
24111
24199
  return {
24112
24200
  capturePane(sessionName) {
24113
24201
  try {
24114
- return execFileSync9("tmux", ["capture-pane", "-p", "-t", sessionName, "-S", "-200"], {
24202
+ return execFileSync10("tmux", ["capture-pane", "-p", "-t", sessionName, "-S", "-200"], {
24115
24203
  encoding: "utf-8",
24116
24204
  stdio: ["pipe", "pipe", "pipe"]
24117
24205
  }).trim();
@@ -24151,7 +24239,7 @@ import {
24151
24239
  copyFileSync as copyFileSync5,
24152
24240
  existsSync as existsSync19,
24153
24241
  mkdirSync as mkdirSync14,
24154
- readFileSync as readFileSync17,
24242
+ readFileSync as readFileSync18,
24155
24243
  readdirSync as readdirSync9,
24156
24244
  renameSync as renameSync6,
24157
24245
  rmSync as rmSync4,
@@ -24206,7 +24294,7 @@ function readActiveSlot(agentDir) {
24206
24294
  if (!existsSync19(p))
24207
24295
  return null;
24208
24296
  try {
24209
- const val = readFileSync17(p, "utf-8").trim();
24297
+ const val = readFileSync18(p, "utf-8").trim();
24210
24298
  return val.length > 0 ? val : null;
24211
24299
  } catch {
24212
24300
  return null;
@@ -24242,7 +24330,7 @@ function readSlotMeta(agentDir, slot) {
24242
24330
  if (!existsSync19(p))
24243
24331
  return null;
24244
24332
  try {
24245
- return JSON.parse(readFileSync17(p, "utf-8"));
24333
+ return JSON.parse(readFileSync18(p, "utf-8"));
24246
24334
  } catch {
24247
24335
  return null;
24248
24336
  }
@@ -24291,7 +24379,7 @@ function syncLegacyFromActive(agentDir) {
24291
24379
  }
24292
24380
  }
24293
24381
  function atomicCopy(src, dest, mode) {
24294
- const contents = readFileSync17(src);
24382
+ const contents = readFileSync18(src);
24295
24383
  const tmp = `${dest}.tmp-${process.pid}-${randomBytes2(4).toString("hex")}`;
24296
24384
  try {
24297
24385
  writeFileSync9(tmp, contents, { mode });
@@ -24320,7 +24408,7 @@ function migrateLegacyIfNeeded(agentDir) {
24320
24408
  }
24321
24409
  let token;
24322
24410
  try {
24323
- token = readFileSync17(legacyToken, "utf-8").trim();
24411
+ token = readFileSync18(legacyToken, "utf-8").trim();
24324
24412
  } catch {
24325
24413
  return { migrated: false };
24326
24414
  }
@@ -24392,9 +24480,9 @@ var init_accounts = __esm(() => {
24392
24480
  });
24393
24481
 
24394
24482
  // src/auth/manager.ts
24395
- import { execFileSync as execFileSync10 } from "node:child_process";
24483
+ import { execFileSync as execFileSync11 } from "node:child_process";
24396
24484
  import {
24397
- readFileSync as readFileSync18,
24485
+ readFileSync as readFileSync19,
24398
24486
  readdirSync as readdirSync10,
24399
24487
  existsSync as existsSync20,
24400
24488
  writeFileSync as writeFileSync10,
@@ -24443,14 +24531,14 @@ function authSessionName(name, slot) {
24443
24531
  return `${base}-${slot.replace(/[^a-zA-Z0-9_.-]/g, "-")}`;
24444
24532
  }
24445
24533
  function tmux(args) {
24446
- return execFileSync10("tmux", args, {
24534
+ return execFileSync11("tmux", args, {
24447
24535
  encoding: "utf-8",
24448
24536
  stdio: ["pipe", "pipe", "pipe"]
24449
24537
  }).trim();
24450
24538
  }
24451
24539
  function tmuxSessionExists(sessionName) {
24452
24540
  try {
24453
- execFileSync10("tmux", ["has-session", "-t", sessionName], {
24541
+ execFileSync11("tmux", ["has-session", "-t", sessionName], {
24454
24542
  stdio: ["pipe", "pipe", "pipe"]
24455
24543
  });
24456
24544
  return true;
@@ -24465,7 +24553,7 @@ function readJsonFile(path) {
24465
24553
  if (!existsSync20(path))
24466
24554
  return null;
24467
24555
  try {
24468
- return JSON.parse(readFileSync18(path, "utf-8"));
24556
+ return JSON.parse(readFileSync19(path, "utf-8"));
24469
24557
  } catch {
24470
24558
  return null;
24471
24559
  }
@@ -24475,7 +24563,7 @@ function readOAuthToken(agentDir) {
24475
24563
  if (!existsSync20(path))
24476
24564
  return null;
24477
24565
  try {
24478
- const token = readFileSync18(path, "utf-8").trim();
24566
+ const token = readFileSync19(path, "utf-8").trim();
24479
24567
  return token.length > 0 ? token : null;
24480
24568
  } catch {
24481
24569
  return null;
@@ -24487,7 +24575,7 @@ function authFilesAreInaccessible(agentDir) {
24487
24575
  if (!existsSync20(p))
24488
24576
  continue;
24489
24577
  try {
24490
- readFileSync18(p, "utf-8");
24578
+ readFileSync19(p, "utf-8");
24491
24579
  } catch (err) {
24492
24580
  const code = err?.code;
24493
24581
  if (code === "EACCES" || code === "EPERM")
@@ -24586,7 +24674,7 @@ function readTokenFromCredentialsFile(credentialsFilePath) {
24586
24674
  try {
24587
24675
  if (!existsSync20(credentialsFilePath))
24588
24676
  return null;
24589
- const raw = readFileSync18(credentialsFilePath, "utf-8");
24677
+ const raw = readFileSync19(credentialsFilePath, "utf-8");
24590
24678
  const parsed = JSON.parse(raw);
24591
24679
  const token = parsed?.claudeAiOauth?.accessToken;
24592
24680
  if (typeof token !== "string")
@@ -24610,7 +24698,7 @@ function readCredentials(agentDir) {
24610
24698
  if (!existsSync20(credPath))
24611
24699
  return null;
24612
24700
  try {
24613
- const parsed = JSON.parse(readFileSync18(credPath, "utf-8"));
24701
+ const parsed = JSON.parse(readFileSync19(credPath, "utf-8"));
24614
24702
  return parsed.claudeAiOauth ?? null;
24615
24703
  } catch {
24616
24704
  return null;
@@ -24766,7 +24854,7 @@ function readTokenFromLogFile(logPath) {
24766
24854
  if (!existsSync20(logPath))
24767
24855
  return null;
24768
24856
  try {
24769
- const content = readFileSync18(logPath, "utf-8");
24857
+ const content = readFileSync19(logPath, "utf-8");
24770
24858
  return parseSetupTokenValue(content);
24771
24859
  } catch {
24772
24860
  return null;
@@ -24912,7 +25000,7 @@ var init_manager = __esm(() => {
24912
25000
  import {
24913
25001
  existsSync as existsSync25,
24914
25002
  mkdirSync as mkdirSync16,
24915
- readFileSync as readFileSync20,
25003
+ readFileSync as readFileSync21,
24916
25004
  unlinkSync as unlinkSync6,
24917
25005
  writeFileSync as writeFileSync12
24918
25006
  } from "node:fs";
@@ -24925,7 +25013,7 @@ function readQuarantineMarker(telegramStateDir) {
24925
25013
  if (!existsSync25(path))
24926
25014
  return null;
24927
25015
  try {
24928
- const raw = readFileSync20(path, "utf-8");
25016
+ const raw = readFileSync21(path, "utf-8");
24929
25017
  const parsed = JSON.parse(raw);
24930
25018
  if (!parsed || typeof parsed !== "object")
24931
25019
  return null;
@@ -24981,7 +25069,7 @@ __export(exports_inject, {
24981
25069
  INJECT_BLOCKED: () => INJECT_BLOCKED,
24982
25070
  INJECT_ALLOWLIST: () => INJECT_ALLOWLIST
24983
25071
  });
24984
- import { execFile, execFileSync as execFileSync12 } from "node:child_process";
25072
+ import { execFile, execFileSync as execFileSync13 } from "node:child_process";
24985
25073
  import { promisify } from "node:util";
24986
25074
  function validateInjectCommand(command) {
24987
25075
  if (typeof command !== "string" || command.trim().length === 0) {
@@ -25009,7 +25097,7 @@ function makeTmuxRunner(tmuxBin) {
25009
25097
  return {
25010
25098
  capture(socket, session) {
25011
25099
  try {
25012
- return execFileSync12(tmuxBin, ["-L", socket, "capture-pane", "-p", "-t", session, "-S", "-200"], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
25100
+ return execFileSync13(tmuxBin, ["-L", socket, "capture-pane", "-p", "-t", session, "-S", "-200"], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
25013
25101
  } catch {
25014
25102
  return null;
25015
25103
  }
@@ -25019,11 +25107,11 @@ function makeTmuxRunner(tmuxBin) {
25019
25107
  const flagEnd = rest.findIndex((a) => !a.startsWith("-"));
25020
25108
  const flagsBeforeKeys = flagEnd === -1 ? rest : rest.slice(0, flagEnd);
25021
25109
  const keys = flagEnd === -1 ? [] : rest.slice(flagEnd);
25022
- execFileSync12(tmuxBin, ["-L", socket, subcmd, ...flagsBeforeKeys, "-t", session, ...keys], { stdio: ["pipe", "pipe", "pipe"] });
25110
+ execFileSync13(tmuxBin, ["-L", socket, subcmd, ...flagsBeforeKeys, "-t", session, ...keys], { stdio: ["pipe", "pipe", "pipe"] });
25023
25111
  },
25024
25112
  hasSession(socket, session) {
25025
25113
  try {
25026
- execFileSync12(tmuxBin, ["-L", socket, "has-session", "-t", session], {
25114
+ execFileSync13(tmuxBin, ["-L", socket, "has-session", "-t", session], {
25027
25115
  stdio: ["pipe", "pipe", "pipe"]
25028
25116
  });
25029
25117
  return true;
@@ -25856,7 +25944,7 @@ import {
25856
25944
  chownSync,
25857
25945
  existsSync as existsSync28,
25858
25946
  mkdirSync as mkdirSync17,
25859
- readFileSync as readFileSync22,
25947
+ readFileSync as readFileSync23,
25860
25948
  readdirSync as readdirSync14,
25861
25949
  renameSync as renameSync7,
25862
25950
  rmSync as rmSync10,
@@ -25904,7 +25992,7 @@ function readAccountCredentials(label, home2 = homedir9()) {
25904
25992
  if (!existsSync28(p))
25905
25993
  return null;
25906
25994
  try {
25907
- return JSON.parse(readFileSync22(p, "utf-8"));
25995
+ return JSON.parse(readFileSync23(p, "utf-8"));
25908
25996
  } catch {
25909
25997
  return null;
25910
25998
  }
@@ -25914,7 +26002,7 @@ function readAccountMeta(label, home2 = homedir9()) {
25914
26002
  if (!existsSync28(p))
25915
26003
  return null;
25916
26004
  try {
25917
- return JSON.parse(readFileSync22(p, "utf-8"));
26005
+ return JSON.parse(readFileSync23(p, "utf-8"));
25918
26006
  } catch {
25919
26007
  return null;
25920
26008
  }
@@ -25964,9 +26052,9 @@ function setGoogleWorkspaceBlock(yamlText, block) {
25964
26052
  if (!Array.isArray(block.approvers) || block.approvers.length === 0) {
25965
26053
  throw new Error("setGoogleWorkspaceBlock: at least one approver id is required");
25966
26054
  }
25967
- const doc = import_yaml6.parseDocument(yamlText);
26055
+ const doc = import_yaml7.parseDocument(yamlText);
25968
26056
  const root = doc.contents;
25969
- if (!import_yaml6.isMap(root)) {
26057
+ if (!import_yaml7.isMap(root)) {
25970
26058
  throw new Error("setGoogleWorkspaceBlock: YAML root is not a map");
25971
26059
  }
25972
26060
  if (root.has("google_workspace") || root.has("drive")) {
@@ -25983,9 +26071,9 @@ function setGoogleWorkspaceBlock(yamlText, block) {
25983
26071
  `) ? out : out + `
25984
26072
  `;
25985
26073
  }
25986
- var import_yaml6;
26074
+ var import_yaml7;
25987
26075
  var init_google_workspace_yaml = __esm(() => {
25988
- import_yaml6 = __toESM(require_dist(), 1);
26076
+ import_yaml7 = __toESM(require_dist(), 1);
25989
26077
  });
25990
26078
 
25991
26079
  // src/util/atomic.ts
@@ -27655,13 +27743,13 @@ function setAuthActive(yamlText, label) {
27655
27743
  if (typeof label !== "string" || label.length === 0) {
27656
27744
  throw new Error("setAuthActive: label must be a non-empty string");
27657
27745
  }
27658
- const doc = import_yaml8.parseDocument(yamlText);
27746
+ const doc = import_yaml9.parseDocument(yamlText);
27659
27747
  const root = doc.contents;
27660
- if (!import_yaml8.isMap(root)) {
27748
+ if (!import_yaml9.isMap(root)) {
27661
27749
  throw new Error("setAuthActive: YAML root is not a map");
27662
27750
  }
27663
27751
  const existing = root.get("auth", true);
27664
- if (import_yaml8.isMap(existing)) {
27752
+ if (import_yaml9.isMap(existing)) {
27665
27753
  if (existing.get("active") === label) {
27666
27754
  return yamlText;
27667
27755
  }
@@ -27674,9 +27762,9 @@ function setAuthActive(yamlText, label) {
27674
27762
  `) ? out : out + `
27675
27763
  `;
27676
27764
  }
27677
- var import_yaml8;
27765
+ var import_yaml9;
27678
27766
  var init_auth_active_yaml = __esm(() => {
27679
- import_yaml8 = __toESM(require_dist(), 1);
27767
+ import_yaml9 = __toESM(require_dist(), 1);
27680
27768
  });
27681
27769
 
27682
27770
  // src/auth/via-claude.ts
@@ -27690,8 +27778,8 @@ __export(exports_via_claude, {
27690
27778
  PRE_PASTE_RULES: () => PRE_PASTE_RULES,
27691
27779
  POST_PASTE_RULES: () => POST_PASTE_RULES
27692
27780
  });
27693
- import { execFileSync as execFileSync13, spawnSync as spawnSync2 } from "node:child_process";
27694
- import { existsSync as existsSync30, mkdirSync as mkdirSync18, readFileSync as readFileSync25 } from "node:fs";
27781
+ import { execFileSync as execFileSync14, spawnSync as spawnSync2 } from "node:child_process";
27782
+ import { existsSync as existsSync30, mkdirSync as mkdirSync18, readFileSync as readFileSync26 } from "node:fs";
27695
27783
  import { join as join22, resolve as resolve23 } from "node:path";
27696
27784
  function tmuxHasSession(session) {
27697
27785
  const r = spawnSync2("tmux", ["has-session", "-t", session], {
@@ -27701,7 +27789,7 @@ function tmuxHasSession(session) {
27701
27789
  }
27702
27790
  function tmuxKillSession(session) {
27703
27791
  try {
27704
- execFileSync13("tmux", ["kill-session", "-t", session], {
27792
+ execFileSync14("tmux", ["kill-session", "-t", session], {
27705
27793
  stdio: "ignore",
27706
27794
  timeout: 3000
27707
27795
  });
@@ -27709,7 +27797,7 @@ function tmuxKillSession(session) {
27709
27797
  }
27710
27798
  function tmuxCapturePane(session) {
27711
27799
  try {
27712
- const out = execFileSync13("tmux", ["capture-pane", "-p", "-t", session, "-S", "-200"], { timeout: 3000, stdio: ["ignore", "pipe", "pipe"], maxBuffer: 4 * 1024 * 1024 });
27800
+ const out = execFileSync14("tmux", ["capture-pane", "-p", "-t", session, "-S", "-200"], { timeout: 3000, stdio: ["ignore", "pipe", "pipe"], maxBuffer: 4 * 1024 * 1024 });
27713
27801
  return out.toString("utf8");
27714
27802
  } catch {
27715
27803
  return "";
@@ -27717,7 +27805,7 @@ function tmuxCapturePane(session) {
27717
27805
  }
27718
27806
  function tmuxSendKeys(session, keys, literal = false) {
27719
27807
  try {
27720
- execFileSync13("tmux", ["send-keys", "-t", session, ...literal ? ["-l"] : [], ...keys], { timeout: 3000, stdio: ["ignore", "pipe", "pipe"] });
27808
+ execFileSync14("tmux", ["send-keys", "-t", session, ...literal ? ["-l"] : [], ...keys], { timeout: 3000, stdio: ["ignore", "pipe", "pipe"] });
27721
27809
  } catch {}
27722
27810
  }
27723
27811
  function extractAuthorizeUrl(pane) {
@@ -27746,7 +27834,7 @@ async function runViaClaude(opts) {
27746
27834
  tmuxKillSession(SESSION);
27747
27835
  }
27748
27836
  const spawn4 = opts.spawnClaude ?? (() => {
27749
- execFileSync13("tmux", [
27837
+ execFileSync14("tmux", [
27750
27838
  "new-session",
27751
27839
  "-d",
27752
27840
  "-s",
@@ -27801,7 +27889,7 @@ async function runViaClaude(opts) {
27801
27889
  await sleep3(poll);
27802
27890
  if (existsSync30(credentialsPath2)) {
27803
27891
  await sleep3(200);
27804
- const raw = readFileSync25(credentialsPath2, "utf-8");
27892
+ const raw = readFileSync26(credentialsPath2, "utf-8");
27805
27893
  let parsed;
27806
27894
  try {
27807
27895
  parsed = JSON.parse(raw);
@@ -28563,7 +28651,7 @@ var init_thinking_effort_risk = __esm(() => {
28563
28651
  // src/manifest.ts
28564
28652
  import {
28565
28653
  existsSync as existsSync49,
28566
- readFileSync as readFileSync44,
28654
+ readFileSync as readFileSync45,
28567
28655
  readdirSync as readdirSync18
28568
28656
  } from "node:fs";
28569
28657
  import { dirname as dirname11, join as join42 } from "node:path";
@@ -28585,7 +28673,7 @@ function loadManifest(manifestPath) {
28585
28673
  }
28586
28674
  let raw;
28587
28675
  try {
28588
- raw = readFileSync44(path4, "utf-8");
28676
+ raw = readFileSync45(path4, "utf-8");
28589
28677
  } catch (err) {
28590
28678
  throw new Error(`Failed to read manifest at ${path4}: ${err.message}`);
28591
28679
  }
@@ -28650,7 +28738,7 @@ function probePlaywrightMcpVersion() {
28650
28738
  const pkgPath = join42(npxCache, entry, "node_modules/@playwright/mcp/package.json");
28651
28739
  if (existsSync49(pkgPath)) {
28652
28740
  try {
28653
- const pkg = JSON.parse(readFileSync44(pkgPath, "utf-8"));
28741
+ const pkg = JSON.parse(readFileSync45(pkgPath, "utf-8"));
28654
28742
  if (pkg.version)
28655
28743
  return pkg.version;
28656
28744
  } catch {}
@@ -28742,13 +28830,22 @@ var init_manifest = __esm(() => {
28742
28830
  });
28743
28831
 
28744
28832
  // src/cli/doctor-docker.ts
28745
- import { readFileSync as readFileSync45 } from "node:fs";
28833
+ import { readFileSync as readFileSync46 } from "node:fs";
28834
+ function imageTagOf(ref) {
28835
+ if (!ref)
28836
+ return "<absent>";
28837
+ const at = ref.lastIndexOf("@");
28838
+ const base = at >= 0 ? ref.slice(0, at) : ref;
28839
+ const colon = base.lastIndexOf(":");
28840
+ const slash = base.lastIndexOf("/");
28841
+ return colon > slash ? base.slice(colon + 1) : ref;
28842
+ }
28746
28843
  function isDockerMode(opts) {
28747
28844
  if (process.env.SWITCHROOM_RUNTIME === "docker")
28748
28845
  return true;
28749
28846
  if (opts?.composePath) {
28750
28847
  try {
28751
- readFileSync45(opts.composePath, "utf8");
28848
+ readFileSync46(opts.composePath, "utf8");
28752
28849
  return true;
28753
28850
  } catch {}
28754
28851
  }
@@ -28883,6 +28980,27 @@ function checkDockerfileUserAlignment(composeYaml, dockerfileAgent) {
28883
28980
  fix: "Drop the USER directive from Dockerfile.agent (preferred \u2014 the image is identity-neutral) or align per-agent UIDs by renaming."
28884
28981
  };
28885
28982
  }
28983
+ function checkSingletonImageDrift(composeYaml, deps) {
28984
+ const drift = detectSingletonDrift({
28985
+ composeFile: "(in-memory)",
28986
+ readCompose: () => composeYaml,
28987
+ inspectImage: deps?.inspectImage
28988
+ });
28989
+ const stale = drift.filter((d) => d.needsRecreate && d.running !== null);
28990
+ if (stale.length === 0) {
28991
+ return {
28992
+ name: "singleton image drift",
28993
+ status: "ok",
28994
+ detail: "vault-broker / approval-kernel / auth-broker match the pinned image"
28995
+ };
28996
+ }
28997
+ return {
28998
+ name: "singleton image drift",
28999
+ status: "warn",
29000
+ detail: "singleton(s) running an image older than the pin: " + stale.map((d) => `${d.service} ${imageTagOf(d.running)}\u2260${imageTagOf(d.pinned)}`).join(", "),
29001
+ fix: "Recreate them \u2014 `switchroom agent restart <any-agent>` now self-heals stale singletons, or `switchroom update` (whole-project recreate)."
29002
+ };
29003
+ }
28886
29004
  function runDockerChecks(args) {
28887
29005
  if (!args.active) {
28888
29006
  return [{
@@ -28896,6 +29014,7 @@ function runDockerChecks(args) {
28896
29014
  out.push(checkAgentCaps(args.config));
28897
29015
  if (args.composeYaml) {
28898
29016
  out.push(checkAgentSocketMounts(args.composeYaml));
29017
+ out.push(checkSingletonImageDrift(args.composeYaml));
28899
29018
  if (args.dockerfileAgent) {
28900
29019
  out.push(checkDockerfileUserAlignment(args.composeYaml, args.dockerfileAgent));
28901
29020
  }
@@ -28911,10 +29030,11 @@ function runDockerChecks(args) {
28911
29030
  }
28912
29031
  var init_doctor_docker = __esm(() => {
28913
29032
  init_compose();
29033
+ init_singleton_reconcile();
28914
29034
  });
28915
29035
 
28916
29036
  // src/cli/doctor-auth-broker.ts
28917
- import { existsSync as existsSync50, readFileSync as readFileSync46 } from "node:fs";
29037
+ import { existsSync as existsSync50, readFileSync as readFileSync47 } from "node:fs";
28918
29038
  import { createHash as createHash10 } from "node:crypto";
28919
29039
  import { spawnSync as spawnSync5 } from "node:child_process";
28920
29040
  import { homedir as homedir23 } from "node:os";
@@ -29028,7 +29148,7 @@ function checkAuthBrokerDrift(deps = {}) {
29028
29148
  }
29029
29149
  let index;
29030
29150
  try {
29031
- index = JSON.parse(readFileSync46(indexPath, "utf-8"));
29151
+ index = JSON.parse(readFileSync47(indexPath, "utf-8"));
29032
29152
  } catch (err) {
29033
29153
  return {
29034
29154
  name: "auth-broker: drift",
@@ -29048,7 +29168,7 @@ function checkAuthBrokerDrift(deps = {}) {
29048
29168
  }
29049
29169
  let got;
29050
29170
  try {
29051
- got = sha256Hex(readFileSync46(credsPath, "utf-8"));
29171
+ got = sha256Hex(readFileSync47(credsPath, "utf-8"));
29052
29172
  } catch (err) {
29053
29173
  divergent.push(`${label} (read failed: ${err.message})`);
29054
29174
  continue;
@@ -29089,7 +29209,7 @@ function checkAuthBrokerThresholdViolations(deps = {}) {
29089
29209
  }
29090
29210
  let violations;
29091
29211
  try {
29092
- violations = JSON.parse(readFileSync46(path4, "utf-8"));
29212
+ violations = JSON.parse(readFileSync47(path4, "utf-8"));
29093
29213
  } catch (err) {
29094
29214
  return {
29095
29215
  name: "auth-broker: threshold violations",
@@ -30586,7 +30706,7 @@ function runInlinedSecretChecks(_config, deps = {}) {
30586
30706
  }
30587
30707
  let parsed;
30588
30708
  try {
30589
- parsed = import_yaml14.parse(raw);
30709
+ parsed = import_yaml15.parse(raw);
30590
30710
  } catch {
30591
30711
  return [
30592
30712
  {
@@ -30614,9 +30734,9 @@ function runInlinedSecretChecks(_config, deps = {}) {
30614
30734
  fix: `Move it to the per-agent-ACL'd vault: \`switchroom vault set <name>\` ` + `then replace the literal with \`vault:<name>\`. Rotate the exposed ` + `value if any agent may already have read it.`
30615
30735
  }));
30616
30736
  }
30617
- var import_yaml14, SECRET_KEY_EXACT;
30737
+ var import_yaml15, SECRET_KEY_EXACT;
30618
30738
  var init_doctor_inlined_secrets = __esm(() => {
30619
- import_yaml14 = __toESM(require_dist(), 1);
30739
+ import_yaml15 = __toESM(require_dist(), 1);
30620
30740
  SECRET_KEY_EXACT = new Set([
30621
30741
  "bot_token",
30622
30742
  "client_secret",
@@ -30868,7 +30988,7 @@ var init_doctor_agent_smoke = __esm(() => {
30868
30988
  });
30869
30989
 
30870
30990
  // src/cli/doctor-vault-broker-durability.ts
30871
- import { execFileSync as execFileSync16 } from "node:child_process";
30991
+ import { execFileSync as execFileSync17 } from "node:child_process";
30872
30992
  import { existsSync as existsSync53, statSync as statSync22 } from "node:fs";
30873
30993
  import { homedir as homedir32 } from "node:os";
30874
30994
  import { join as join53 } from "node:path";
@@ -30930,7 +31050,7 @@ function spawnDockerStat(p) {
30930
31050
  }
30931
31051
  function spawnDockerStatForContainer(containerName2, p) {
30932
31052
  try {
30933
- const stdout = execFileSync16("docker", ["exec", containerName2, "stat", "-c", "%i %s", p], { stdio: ["ignore", "pipe", "pipe"], timeout: 3000, encoding: "utf8" });
31053
+ const stdout = execFileSync17("docker", ["exec", containerName2, "stat", "-c", "%i %s", p], { stdio: ["ignore", "pipe", "pipe"], timeout: 3000, encoding: "utf8" });
30934
31054
  return { status: 0, stdout, stderr: "", error: null };
30935
31055
  } catch (err) {
30936
31056
  const e = err;
@@ -31004,7 +31124,7 @@ function probeBrokerUnlocked(opts) {
31004
31124
  }
31005
31125
  function defaultBrokerStatusProbe() {
31006
31126
  try {
31007
- const out = execFileSync16("switchroom", ["vault", "broker", "status"], { stdio: ["ignore", "pipe", "pipe"], timeout: 3000, encoding: "utf8" });
31127
+ const out = execFileSync17("switchroom", ["vault", "broker", "status"], { stdio: ["ignore", "pipe", "pipe"], timeout: 3000, encoding: "utf8" });
31008
31128
  const parsed = JSON.parse(out.trim());
31009
31129
  if (!parsed.running)
31010
31130
  return null;
@@ -31204,7 +31324,7 @@ import {
31204
31324
  existsSync as existsSync54,
31205
31325
  lstatSync as lstatSync5,
31206
31326
  mkdirSync as mkdirSync29,
31207
- readFileSync as readFileSync47,
31327
+ readFileSync as readFileSync48,
31208
31328
  readdirSync as readdirSync20,
31209
31329
  statSync as statSync23
31210
31330
  } from "node:fs";
@@ -31882,7 +32002,7 @@ function classifyReadError(err) {
31882
32002
  }
31883
32003
  function tryReadHostFile(path4) {
31884
32004
  try {
31885
- return { kind: "ok", content: readFileSync47(path4, "utf-8") };
32005
+ return { kind: "ok", content: readFileSync48(path4, "utf-8") };
31886
32006
  } catch (err) {
31887
32007
  const kind = classifyReadError(err);
31888
32008
  const error = err?.message ?? String(err);
@@ -31898,7 +32018,7 @@ function parseEnvFile(path4) {
31898
32018
  return {};
31899
32019
  let content;
31900
32020
  try {
31901
- content = readFileSync47(path4, "utf-8");
32021
+ content = readFileSync48(path4, "utf-8");
31902
32022
  } catch {
31903
32023
  return {};
31904
32024
  }
@@ -32015,7 +32135,7 @@ function checkStartShStale(agentName, startShPath) {
32015
32135
  }
32016
32136
  let content;
32017
32137
  try {
32018
- content = readFileSync47(startShPath, "utf-8");
32138
+ content = readFileSync48(startShPath, "utf-8");
32019
32139
  } catch (err) {
32020
32140
  return {
32021
32141
  name: label,
@@ -32128,7 +32248,7 @@ function isSwitchroomCheckout(dir) {
32128
32248
  const pkgPath = join54(dir, "package.json");
32129
32249
  if (!existsSync54(pkgPath))
32130
32250
  return false;
32131
- const pkg = JSON.parse(readFileSync47(pkgPath, "utf-8"));
32251
+ const pkg = JSON.parse(readFileSync48(pkgPath, "utf-8"));
32132
32252
  return pkg.name === "switchroom";
32133
32253
  } catch {
32134
32254
  return false;
@@ -32249,7 +32369,7 @@ function checkAgents(config, configPath) {
32249
32369
  });
32250
32370
  } else {
32251
32371
  try {
32252
- const mcp = JSON.parse(readFileSync47(mcpJsonPath, "utf-8"));
32372
+ const mcp = JSON.parse(readFileSync48(mcpJsonPath, "utf-8"));
32253
32373
  const hasSwitchroomTelegram = !!mcp.mcpServers?.["switchroom-telegram"];
32254
32374
  const memoryEnabled = isHindsightEnabled(config);
32255
32375
  const hasHindsight = !!mcp.mcpServers?.hindsight;
@@ -32744,11 +32864,11 @@ function runDockerSection(config) {
32744
32864
  let composeYaml;
32745
32865
  let dockerfileAgent;
32746
32866
  try {
32747
- composeYaml = readFileSync47(composePath, "utf8");
32867
+ composeYaml = readFileSync48(composePath, "utf8");
32748
32868
  } catch {}
32749
32869
  const dockerfilePath = resolve32(process.env.HOME ?? "", ".switchroom", "docker", "Dockerfile.agent");
32750
32870
  try {
32751
- dockerfileAgent = readFileSync47(dockerfilePath, "utf8");
32871
+ dockerfileAgent = readFileSync48(dockerfilePath, "utf8");
32752
32872
  } catch {}
32753
32873
  return runDockerChecks({
32754
32874
  config,
@@ -49041,7 +49161,7 @@ __export(exports_server2, {
49041
49161
  TOOLS: () => TOOLS2
49042
49162
  });
49043
49163
  import { randomBytes as randomBytes15 } from "node:crypto";
49044
- import { existsSync as existsSync82, readFileSync as readFileSync66 } from "node:fs";
49164
+ import { existsSync as existsSync82, readFileSync as readFileSync67 } from "node:fs";
49045
49165
  function selfSocketPath() {
49046
49166
  return `/run/switchroom/hostd/${SELF_AGENT}/sock`;
49047
49167
  }
@@ -49219,7 +49339,7 @@ function getLastUpdateApplyStatus() {
49219
49339
  }
49220
49340
  let raw;
49221
49341
  try {
49222
- raw = readFileSync66(path8, "utf-8");
49342
+ raw = readFileSync67(path8, "utf-8");
49223
49343
  } catch (err2) {
49224
49344
  return errorText2(`get_status: failed to read audit log at ${path8}: ${err2.message}`);
49225
49345
  }
@@ -49452,13 +49572,13 @@ var {
49452
49572
  } = import__.default;
49453
49573
 
49454
49574
  // src/build-info.ts
49455
- var VERSION = "0.14.66";
49456
- var COMMIT_SHA = "0f4f029d";
49575
+ var VERSION = "0.14.67";
49576
+ var COMMIT_SHA = "dcade213";
49457
49577
 
49458
49578
  // src/cli/agent.ts
49459
49579
  init_source();
49460
49580
  import { join as join17, resolve as resolve21 } from "node:path";
49461
- import { rmSync as rmSync9, existsSync as existsSync26, readFileSync as readFileSync21, writeFileSync as writeFileSync13 } from "node:fs";
49581
+ import { rmSync as rmSync9, existsSync as existsSync26, readFileSync as readFileSync22, writeFileSync as writeFileSync13 } from "node:fs";
49462
49582
  import { homedir as homedir6 } from "node:os";
49463
49583
 
49464
49584
  // src/agents/scheduler-state.ts
@@ -49524,7 +49644,7 @@ function formatSchedulerState(state) {
49524
49644
  init_loader();
49525
49645
  init_hindsight();
49526
49646
  init_helpers();
49527
- var import_yaml4 = __toESM(require_dist(), 1);
49647
+ var import_yaml5 = __toESM(require_dist(), 1);
49528
49648
 
49529
49649
  // src/agents/scaffold.ts
49530
49650
  init_source();
@@ -53079,12 +53199,12 @@ function spinner(message) {
53079
53199
  }
53080
53200
 
53081
53201
  // src/agents/status.ts
53082
- import { existsSync as existsSync18, readFileSync as readFileSync16, statSync as statSync10 } from "node:fs";
53202
+ import { existsSync as existsSync18, readFileSync as readFileSync17, statSync as statSync10 } from "node:fs";
53083
53203
  import { join as join12 } from "node:path";
53084
- import { execFileSync as execFileSync8 } from "node:child_process";
53204
+ import { execFileSync as execFileSync9 } from "node:child_process";
53085
53205
 
53086
53206
  // src/agents/handoff-summarizer.ts
53087
- import { readFileSync as readFileSync14, writeFileSync as writeFileSync8, renameSync as renameSync5, mkdirSync as mkdirSync13, existsSync as existsSync16, statSync as statSync9, readdirSync as readdirSync8 } from "node:fs";
53207
+ 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";
53088
53208
  import { join as join11 } from "node:path";
53089
53209
  var DEFAULT_MAX_TURNS = 50;
53090
53210
  var TOPIC_MAX_CHARS = 117;
@@ -53092,7 +53212,7 @@ var TURN_TEXT_MAX_CHARS = 1200;
53092
53212
  function extractTurnsFromJsonl(path, maxTurns) {
53093
53213
  let raw;
53094
53214
  try {
53095
- raw = readFileSync14(path, "utf-8");
53215
+ raw = readFileSync15(path, "utf-8");
53096
53216
  } catch {
53097
53217
  return [];
53098
53218
  }
@@ -53317,7 +53437,7 @@ function findLatestSessionJsonl(claudeConfigDir) {
53317
53437
  }
53318
53438
 
53319
53439
  // src/agents/perf.ts
53320
- import { existsSync as existsSync17, readFileSync as readFileSync15 } from "node:fs";
53440
+ import { existsSync as existsSync17, readFileSync as readFileSync16 } from "node:fs";
53321
53441
  function readTurnUsages(jsonlPath, lastN) {
53322
53442
  if (!existsSync17(jsonlPath))
53323
53443
  return [];
@@ -53325,7 +53445,7 @@ function readTurnUsages(jsonlPath, lastN) {
53325
53445
  return [];
53326
53446
  let raw;
53327
53447
  try {
53328
- raw = readFileSync15(jsonlPath, "utf-8");
53448
+ raw = readFileSync16(jsonlPath, "utf-8");
53329
53449
  } catch {
53330
53450
  return [];
53331
53451
  }
@@ -53734,7 +53854,7 @@ function readLogFile(logPath) {
53734
53854
  const stat = statSync10(logPath);
53735
53855
  const cap = 256 * 1024;
53736
53856
  if (stat.size <= cap) {
53737
- return readFileSync16(logPath, "utf-8");
53857
+ return readFileSync17(logPath, "utf-8");
53738
53858
  }
53739
53859
  const fs2 = __require("node:fs");
53740
53860
  const fd = fs2.openSync(logPath, "r");
@@ -53758,14 +53878,14 @@ function readLastMessages(historyDbPath) {
53758
53878
  };
53759
53879
  }
53760
53880
  try {
53761
- const out = execFileSync8("bun", [
53881
+ const out = execFileSync9("bun", [
53762
53882
  "-e",
53763
53883
  `const { Database } = require("bun:sqlite"); ` + `const db = new Database(${JSON.stringify(historyDbPath)}, { readonly: true }); ` + `const rows = db.prepare("SELECT role, MAX(ts) as ts FROM messages GROUP BY role").all(); ` + `for (const r of rows) console.log(r.role + "|" + r.ts); ` + `db.close();`
53764
53884
  ], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
53765
53885
  return parseSqliteRoleTsOutput(out);
53766
53886
  } catch {}
53767
53887
  try {
53768
- const out = execFileSync8("sqlite3", [
53888
+ const out = execFileSync9("sqlite3", [
53769
53889
  historyDbPath,
53770
53890
  "SELECT role, MAX(ts) FROM messages GROUP BY role;"
53771
53891
  ], { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
@@ -53877,7 +53997,7 @@ function escapeRegex(s) {
53877
53997
  }
53878
53998
  function readDockerContainer(containerName2) {
53879
53999
  try {
53880
- const out = execFileSync8("docker", ["inspect", "--format", "{{json .State}}", containerName2], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
54000
+ const out = execFileSync9("docker", ["inspect", "--format", "{{json .State}}", containerName2], { encoding: "utf-8", stdio: ["ignore", "pipe", "pipe"] });
53881
54001
  const state = JSON.parse(out.trim());
53882
54002
  const active = state.Status === "running" ? "active" : state.Status === "restarting" ? "restarting" : "inactive";
53883
54003
  const pid = typeof state.Pid === "number" && state.Pid > 0 ? state.Pid : null;
@@ -54153,7 +54273,7 @@ async function completeCreation(name, code, opts = {}) {
54153
54273
  // src/agents/add-orchestrator.ts
54154
54274
  import { resolve as resolve18, join as join15 } from "node:path";
54155
54275
  import { existsSync as existsSync23, rmSync as rmSync7, statSync as statSync14 } from "node:fs";
54156
- import { execFileSync as execFileSync11 } from "node:child_process";
54276
+ import { execFileSync as execFileSync12 } from "node:child_process";
54157
54277
 
54158
54278
  // src/setup/botfather-walkthrough.ts
54159
54279
  var DEFAULT_MAX_ATTEMPTS = 3;
@@ -54725,7 +54845,7 @@ function pruneBundledSkills(agentDir, keep, scope) {
54725
54845
  }
54726
54846
  function defaultIsUnitActive(unitName) {
54727
54847
  try {
54728
- const out = execFileSync11("systemctl", ["--user", "is-active", unitName], {
54848
+ const out = execFileSync12("systemctl", ["--user", "is-active", unitName], {
54729
54849
  encoding: "utf-8",
54730
54850
  stdio: ["ignore", "pipe", "pipe"]
54731
54851
  }).trim();
@@ -54754,8 +54874,8 @@ import { tmpdir as tmpdir2 } from "node:os";
54754
54874
  init_merge();
54755
54875
  init_timezone();
54756
54876
  init_resolver();
54757
- var import_yaml3 = __toESM(require_dist(), 1);
54758
- import { readFileSync as readFileSync19, writeFileSync as writeFileSync11 } from "node:fs";
54877
+ var import_yaml4 = __toESM(require_dist(), 1);
54878
+ import { readFileSync as readFileSync20, writeFileSync as writeFileSync11 } from "node:fs";
54759
54879
  var AGENT_NAME_RE2 = /^[a-z0-9][a-z0-9_-]{0,50}$/;
54760
54880
  function defaultDeps() {
54761
54881
  return {
@@ -54778,12 +54898,12 @@ function defaultDeps() {
54778
54898
  copyDir: (src, dst) => cpSync(src, dst, { recursive: true }),
54779
54899
  removeDir: (p) => rmSync8(p, { recursive: true, force: true }),
54780
54900
  existsSync: existsSync24,
54781
- readFileSync: (p, enc) => readFileSync19(p, enc)
54901
+ readFileSync: (p, enc) => readFileSync20(p, enc)
54782
54902
  };
54783
54903
  }
54784
54904
  function renameAgentInConfig(configPath, oldName, newName) {
54785
- const raw = readFileSync19(configPath, "utf-8");
54786
- const doc = import_yaml3.default.parseDocument(raw);
54905
+ const raw = readFileSync20(configPath, "utf-8");
54906
+ const doc = import_yaml4.default.parseDocument(raw);
54787
54907
  const agents = doc.get("agents");
54788
54908
  if (!agents || !agents.has(oldName)) {
54789
54909
  throw new Error(`Agent "${oldName}" not found in ${configPath}`);
@@ -54825,7 +54945,7 @@ async function renameAgent(opts, injectedDeps) {
54825
54945
  const deps = { ...defaultDeps(), ...injectedDeps };
54826
54946
  const { oldName, newName, configPath, hindsightMode = "preserve" } = opts;
54827
54947
  const _existsSync = deps.existsSync;
54828
- const _readFileSync = deps.readFileSync ?? ((p, enc) => readFileSync19(p, enc));
54948
+ const _readFileSync = deps.readFileSync ?? ((p, enc) => readFileSync20(p, enc));
54829
54949
  if (!AGENT_NAME_RE2.test(oldName)) {
54830
54950
  throw new Error(`Invalid old agent name: "${oldName}". ` + `Names must match ^[a-z0-9][a-z0-9_-]{0,50}$`);
54831
54951
  }
@@ -55145,16 +55265,16 @@ function parsePorcelainDirty(porcelain) {
55145
55265
  }
55146
55266
  function checkSwitchroomBranch() {
55147
55267
  try {
55148
- const { execFileSync: execFileSync13 } = __require("node:child_process");
55268
+ const { execFileSync: execFileSync14 } = __require("node:child_process");
55149
55269
  const cwd = process.cwd();
55150
- const branch = execFileSync13("git", ["-C", cwd, "rev-parse", "--abbrev-ref", "HEAD"], {
55270
+ const branch = execFileSync14("git", ["-C", cwd, "rev-parse", "--abbrev-ref", "HEAD"], {
55151
55271
  encoding: "utf-8",
55152
55272
  stdio: ["ignore", "pipe", "ignore"]
55153
55273
  }).trim();
55154
55274
  if (branch === "" || branch === "HEAD")
55155
55275
  return null;
55156
55276
  if (branch === "main" || branch === "master") {
55157
- const porcelain = execFileSync13("git", ["-C", cwd, "status", "--porcelain"], {
55277
+ const porcelain = execFileSync14("git", ["-C", cwd, "status", "--porcelain"], {
55158
55278
  encoding: "utf-8",
55159
55279
  stdio: ["ignore", "pipe", "ignore"]
55160
55280
  });
@@ -55199,7 +55319,7 @@ function preflightCheck(name, agentDir, _usesDevChannels) {
55199
55319
  }
55200
55320
  const envPath = resolve21(agentDir, "telegram", ".env");
55201
55321
  if (existsSync26(envPath)) {
55202
- const envContent = readFileSync21(envPath, "utf-8");
55322
+ const envContent = readFileSync22(envPath, "utf-8");
55203
55323
  if (!envContent.includes("TELEGRAM_BOT_TOKEN=") || envContent.includes("# Set your bot token")) {
55204
55324
  errors2.push(`telegram/.env is missing TELEGRAM_BOT_TOKEN. ` + `Set it or run: switchroom setup`);
55205
55325
  }
@@ -55286,25 +55406,25 @@ function writeAgentEntryToConfig(configPath, name, profile) {
55286
55406
  if (!existsSync26(configPath)) {
55287
55407
  throw new Error(`switchroom.yaml not found at ${configPath}`);
55288
55408
  }
55289
- const raw = readFileSync21(configPath, "utf-8");
55290
- const doc = import_yaml4.default.parseDocument(raw);
55409
+ const raw = readFileSync22(configPath, "utf-8");
55410
+ const doc = import_yaml5.default.parseDocument(raw);
55291
55411
  let agents = doc.get("agents");
55292
55412
  if (!agents) {
55293
- agents = new import_yaml4.default.YAMLMap;
55413
+ agents = new import_yaml5.default.YAMLMap;
55294
55414
  doc.set("agents", agents);
55295
55415
  }
55296
55416
  if (agents.has(name)) {
55297
55417
  throw new Error(`Agent "${name}" already exists in ${configPath}. Use updateAgentExtendsInConfig to change its profile.`);
55298
55418
  }
55299
- const entry = new import_yaml4.default.YAMLMap;
55419
+ const entry = new import_yaml5.default.YAMLMap;
55300
55420
  entry.set("extends", profile);
55301
55421
  entry.set("topic_name", synthesizeTopicName2(name));
55302
55422
  agents.set(name, entry);
55303
55423
  writeFileSync13(configPath, doc.toString(), "utf-8");
55304
55424
  }
55305
55425
  function updateAgentExtendsInConfig(configPath, name, profile) {
55306
- const raw = readFileSync21(configPath, "utf-8");
55307
- const doc = import_yaml4.default.parseDocument(raw);
55426
+ const raw = readFileSync22(configPath, "utf-8");
55427
+ const doc = import_yaml5.default.parseDocument(raw);
55308
55428
  const agents = doc.get("agents");
55309
55429
  if (!agents || !agents.has(name)) {
55310
55430
  throw new Error(`Agent "${name}" not found in ${configPath}; cannot update extends.`);
@@ -55316,8 +55436,8 @@ function updateAgentExtendsInConfig(configPath, name, profile) {
55316
55436
  function removeAgentFromConfig(configPath, name) {
55317
55437
  if (!existsSync26(configPath))
55318
55438
  return;
55319
- const raw = readFileSync21(configPath, "utf-8");
55320
- const doc = import_yaml4.default.parseDocument(raw);
55439
+ const raw = readFileSync22(configPath, "utf-8");
55440
+ const doc = import_yaml5.default.parseDocument(raw);
55321
55441
  const agents = doc.get("agents");
55322
55442
  if (!agents || !agents.has(name))
55323
55443
  return;
@@ -55362,7 +55482,7 @@ async function reconcileAndRestartAgent(name, config, agentsDir, configPath, opt
55362
55482
  if (!opts.force) {
55363
55483
  const envPath = resolve21(agentsDir, name, "telegram", ".env");
55364
55484
  if (existsSync26(envPath)) {
55365
- const envContent = readFileSync21(envPath, "utf-8");
55485
+ const envContent = readFileSync22(envPath, "utf-8");
55366
55486
  const match = envContent.match(/^TELEGRAM_BOT_TOKEN=(.+)$/m);
55367
55487
  if (match) {
55368
55488
  const token = match[1].trim();
@@ -55637,6 +55757,14 @@ Scaffolding agent: ${name}
55637
55757
  }
55638
55758
  }
55639
55759
  let sawAbort = false;
55760
+ try {
55761
+ const recon = reconcileSingletonImages((m) => console.error(source_default.gray(` ${m}`)));
55762
+ if (recon.recreated.length > 0) {
55763
+ console.error(source_default.cyan(` \u21bb Recreated stale singleton(s) to the pinned image: ${recon.recreated.join(", ")}`));
55764
+ }
55765
+ } catch (err) {
55766
+ console.error(source_default.yellow(` \u26a0 singleton reconcile skipped: ${err instanceof Error ? err.message : String(err)}`));
55767
+ }
55640
55768
  for (const n of names) {
55641
55769
  if (!config.agents[n]) {
55642
55770
  console.error(source_default.red(`Agent "${n}" is not defined in switchroom.yaml`));
@@ -55836,7 +55964,7 @@ Scaffolding agent: ${name}
55836
55964
  let actual = {};
55837
55965
  if (existsSync26(settingsPath)) {
55838
55966
  try {
55839
- const raw = JSON.parse(readFileSync21(settingsPath, "utf-8"));
55967
+ const raw = JSON.parse(readFileSync22(settingsPath, "utf-8"));
55840
55968
  actual = raw.hooks ?? {};
55841
55969
  } catch {
55842
55970
  console.error(source_default.red(` ${n}: could not parse settings.json`));
@@ -55978,8 +56106,8 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
55978
56106
  console.error(source_default.red(`switchroom.yaml not found at ${configPath}`));
55979
56107
  process.exit(1);
55980
56108
  }
55981
- const raw = readFileSync21(configPath, "utf-8");
55982
- const doc = import_yaml4.default.parseDocument(raw);
56109
+ const raw = readFileSync22(configPath, "utf-8");
56110
+ const doc = import_yaml5.default.parseDocument(raw);
55983
56111
  const agents = doc.get("agents");
55984
56112
  if (!agents || !agents.has(name)) {
55985
56113
  console.error(source_default.red(`Agent "${name}" is not defined in switchroom.yaml`));
@@ -55988,12 +56116,12 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
55988
56116
  const agentNode = agents.get(name);
55989
56117
  let tools = agentNode.get("tools");
55990
56118
  if (!tools) {
55991
- tools = new import_yaml4.default.YAMLMap;
56119
+ tools = new import_yaml5.default.YAMLMap;
55992
56120
  agentNode.set("tools", tools);
55993
56121
  }
55994
56122
  let allow = tools.get("allow");
55995
56123
  if (!allow) {
55996
- allow = new import_yaml4.default.YAMLSeq;
56124
+ allow = new import_yaml5.default.YAMLSeq;
55997
56125
  tools.set("allow", allow);
55998
56126
  }
55999
56127
  const existingAllow = allow.toJSON() ?? [];
@@ -56027,8 +56155,8 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
56027
56155
  console.error(source_default.red(`switchroom.yaml not found at ${configPath}`));
56028
56156
  process.exit(1);
56029
56157
  }
56030
- const raw = readFileSync21(configPath, "utf-8");
56031
- const doc = import_yaml4.default.parseDocument(raw);
56158
+ const raw = readFileSync22(configPath, "utf-8");
56159
+ const doc = import_yaml5.default.parseDocument(raw);
56032
56160
  const agents = doc.get("agents");
56033
56161
  if (!agents || !agents.has(name)) {
56034
56162
  console.error(source_default.red(`Agent "${name}" is not defined in switchroom.yaml`));
@@ -56038,7 +56166,7 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
56038
56166
  if (opts.off) {
56039
56167
  const tools = agentNode.get("tools");
56040
56168
  if (tools && tools.has("allow")) {
56041
- tools.set("allow", new import_yaml4.default.YAMLSeq);
56169
+ tools.set("allow", new import_yaml5.default.YAMLSeq);
56042
56170
  writeFileSync13(configPath, doc.toString(), "utf-8");
56043
56171
  console.log(source_default.yellow(` ${name}: dangerous mode OFF (tools.allow cleared)`));
56044
56172
  } else {
@@ -56047,10 +56175,10 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
56047
56175
  } else {
56048
56176
  let tools = agentNode.get("tools");
56049
56177
  if (!tools) {
56050
- tools = new import_yaml4.default.YAMLMap;
56178
+ tools = new import_yaml5.default.YAMLMap;
56051
56179
  agentNode.set("tools", tools);
56052
56180
  }
56053
- const allowSeq = new import_yaml4.default.YAMLSeq;
56181
+ const allowSeq = new import_yaml5.default.YAMLSeq;
56054
56182
  allowSeq.add("all");
56055
56183
  tools.set("allow", allowSeq);
56056
56184
  writeFileSync13(configPath, doc.toString(), "utf-8");
@@ -56082,7 +56210,7 @@ Reconciled ${agentsTouched} agent(s), ${totalChanges} file(s) changed.`));
56082
56210
  console.error(source_default.red(`Agent "${name}" not found at ${settingsPath}`));
56083
56211
  process.exit(1);
56084
56212
  }
56085
- const settings = JSON.parse(readFileSync21(settingsPath, "utf-8"));
56213
+ const settings = JSON.parse(readFileSync22(settingsPath, "utf-8"));
56086
56214
  const allow = settings.permissions?.allow ?? [];
56087
56215
  const deny = settings.permissions?.deny ?? [];
56088
56216
  const defaultMode = settings.permissions?.defaultMode;
@@ -56922,24 +57050,24 @@ init_account_store();
56922
57050
  init_loader();
56923
57051
  init_manager();
56924
57052
  init_helpers();
56925
- import { existsSync as existsSync31, readFileSync as readFileSync26 } from "node:fs";
57053
+ import { existsSync as existsSync31, readFileSync as readFileSync27 } from "node:fs";
56926
57054
  import { join as join23, resolve as resolve24 } from "node:path";
56927
57055
 
56928
57056
  // src/cli/auth-google.ts
56929
57057
  init_source();
56930
- import { readFileSync as readFileSync23, writeFileSync as writeFileSync15 } from "node:fs";
57058
+ import { readFileSync as readFileSync24, writeFileSync as writeFileSync15 } from "node:fs";
56931
57059
 
56932
57060
  // src/cli/google-accounts-yaml.ts
56933
- var import_yaml5 = __toESM(require_dist(), 1);
57061
+ var import_yaml6 = __toESM(require_dist(), 1);
56934
57062
  function enableAgentsOnGoogleAccount(yamlText, account, agentsToEnable) {
56935
- const doc = import_yaml5.parseDocument(yamlText);
57063
+ const doc = import_yaml6.parseDocument(yamlText);
56936
57064
  ensureGoogleAccountEntry(doc, account);
56937
57065
  const existing = doc.getIn(["google_accounts", account, "enabled_for"]);
56938
57066
  const currentAgents = readEnabledFor(existing);
56939
57067
  const additions = agentsToEnable.filter((a) => !currentAgents.includes(a));
56940
57068
  if (additions.length === 0)
56941
57069
  return yamlText;
56942
- if (import_yaml5.isSeq(existing)) {
57070
+ if (import_yaml6.isSeq(existing)) {
56943
57071
  const seq = existing;
56944
57072
  for (const a of additions)
56945
57073
  seq.add(a);
@@ -56949,11 +57077,11 @@ function enableAgentsOnGoogleAccount(yamlText, account, agentsToEnable) {
56949
57077
  return String(doc);
56950
57078
  }
56951
57079
  function disableAgentsOnGoogleAccount(yamlText, account, agentsToDisable) {
56952
- const doc = import_yaml5.parseDocument(yamlText);
57080
+ const doc = import_yaml6.parseDocument(yamlText);
56953
57081
  if (!hasGoogleAccountEntry(doc, account))
56954
57082
  return yamlText;
56955
57083
  const existing = doc.getIn(["google_accounts", account, "enabled_for"]);
56956
- if (!import_yaml5.isSeq(existing))
57084
+ if (!import_yaml6.isSeq(existing))
56957
57085
  return yamlText;
56958
57086
  const seq = existing;
56959
57087
  const beforeLen = seq.items.length;
@@ -56969,16 +57097,16 @@ function disableAgentsOnGoogleAccount(yamlText, account, agentsToDisable) {
56969
57097
  return String(doc);
56970
57098
  }
56971
57099
  function getEnabledAgentsForGoogleAccount(yamlText, account) {
56972
- const doc = import_yaml5.parseDocument(yamlText);
57100
+ const doc = import_yaml6.parseDocument(yamlText);
56973
57101
  if (!hasGoogleAccountEntry(doc, account))
56974
57102
  return null;
56975
57103
  const existing = doc.getIn(["google_accounts", account, "enabled_for"]);
56976
57104
  return readEnabledFor(existing);
56977
57105
  }
56978
57106
  function listGoogleAccounts(yamlText) {
56979
- const doc = import_yaml5.parseDocument(yamlText);
57107
+ const doc = import_yaml6.parseDocument(yamlText);
56980
57108
  const accounts = doc.get("google_accounts");
56981
- if (!import_yaml5.isMap(accounts))
57109
+ if (!import_yaml6.isMap(accounts))
56982
57110
  return [];
56983
57111
  const out = [];
56984
57112
  for (const item of accounts.items) {
@@ -56993,7 +57121,7 @@ function listGoogleAccounts(yamlText) {
56993
57121
  return out;
56994
57122
  }
56995
57123
  function readEnabledFor(node) {
56996
- if (!import_yaml5.isSeq(node))
57124
+ if (!import_yaml6.isSeq(node))
56997
57125
  return [];
56998
57126
  const seq = node;
56999
57127
  return seq.items.map((item) => item.value ?? item).filter((v) => typeof v === "string");
@@ -57005,7 +57133,7 @@ function ensureGoogleAccountEntry(doc, account) {
57005
57133
  }
57006
57134
  function hasGoogleAccountEntry(doc, account) {
57007
57135
  const accounts = doc.get("google_accounts");
57008
- if (!import_yaml5.isMap(accounts))
57136
+ if (!import_yaml6.isMap(accounts))
57009
57137
  return false;
57010
57138
  return accounts.has(account);
57011
57139
  }
@@ -57122,7 +57250,7 @@ function registerConnect(googleParent, program3) {
57122
57250
  ` tier: ${tier}`
57123
57251
  ].join(`
57124
57252
  `);
57125
- const raw = readFileSync23(configPath, "utf-8");
57253
+ const raw = readFileSync24(configPath, "utf-8");
57126
57254
  const patched = setGoogleWorkspaceBlock2(raw, {
57127
57255
  clientIdRef: "vault:google-oauth-client-id",
57128
57256
  clientSecretRef: "vault:google-oauth-client-secret",
@@ -57168,7 +57296,7 @@ function registerEnable(googleParent, program3) {
57168
57296
  }
57169
57297
  }
57170
57298
  const yamlPath = getConfigPath(program3);
57171
- const before = readFileSync23(yamlPath, "utf-8");
57299
+ const before = readFileSync24(yamlPath, "utf-8");
57172
57300
  const after = enableAgentsOnGoogleAccount(before, normalizedAccount, agents);
57173
57301
  const noop = after === before;
57174
57302
  if (!noop) {
@@ -57196,7 +57324,7 @@ function registerDisable(googleParent, program3) {
57196
57324
  const config = getConfig(program3);
57197
57325
  agents = expandAllAgents(agents, config);
57198
57326
  const yamlPath = getConfigPath(program3);
57199
- const before = readFileSync23(yamlPath, "utf-8");
57327
+ const before = readFileSync24(yamlPath, "utf-8");
57200
57328
  const enabledBefore = getEnabledAgentsBefore(before, normalizedAccount);
57201
57329
  if (enabledBefore.length === 0) {
57202
57330
  console.log();
@@ -57233,7 +57361,7 @@ function registerDisable(googleParent, program3) {
57233
57361
  function registerList(googleParent, program3) {
57234
57362
  googleParent.command("list").description("List every Google account configured in switchroom.yaml with its enabled_for[] agents. Matrix view of accounts \u00d7 agents.").option("--json", "Emit raw JSON instead of a table").action(withConfigError(async (opts) => {
57235
57363
  const yamlPath = getConfigPath(program3);
57236
- const yaml = readFileSync23(yamlPath, "utf-8");
57364
+ const yaml = readFileSync24(yamlPath, "utf-8");
57237
57365
  const accounts = listGoogleAccounts(yaml);
57238
57366
  if (opts.json) {
57239
57367
  console.log(JSON.stringify(accounts, null, 2));
@@ -57619,19 +57747,19 @@ function buildGoogleCredentials(args) {
57619
57747
 
57620
57748
  // src/cli/auth-microsoft.ts
57621
57749
  init_source();
57622
- import { readFileSync as readFileSync24, writeFileSync as writeFileSync16 } from "node:fs";
57750
+ import { readFileSync as readFileSync25, writeFileSync as writeFileSync16 } from "node:fs";
57623
57751
 
57624
57752
  // src/cli/microsoft-accounts-yaml.ts
57625
- var import_yaml7 = __toESM(require_dist(), 1);
57753
+ var import_yaml8 = __toESM(require_dist(), 1);
57626
57754
  function enableAgentsOnMicrosoftAccount(yamlText, account, agentsToEnable) {
57627
- const doc = import_yaml7.parseDocument(yamlText);
57755
+ const doc = import_yaml8.parseDocument(yamlText);
57628
57756
  ensureMicrosoftAccountEntry(doc, account);
57629
57757
  const existing = doc.getIn(["microsoft_accounts", account, "enabled_for"]);
57630
57758
  const currentAgents = readEnabledFor2(existing);
57631
57759
  const additions = agentsToEnable.filter((a) => !currentAgents.includes(a));
57632
57760
  if (additions.length === 0)
57633
57761
  return yamlText;
57634
- if (import_yaml7.isSeq(existing)) {
57762
+ if (import_yaml8.isSeq(existing)) {
57635
57763
  const seq = existing;
57636
57764
  for (const a of additions)
57637
57765
  seq.add(a);
@@ -57641,11 +57769,11 @@ function enableAgentsOnMicrosoftAccount(yamlText, account, agentsToEnable) {
57641
57769
  return String(doc);
57642
57770
  }
57643
57771
  function disableAgentsOnMicrosoftAccount(yamlText, account, agentsToDisable) {
57644
- const doc = import_yaml7.parseDocument(yamlText);
57772
+ const doc = import_yaml8.parseDocument(yamlText);
57645
57773
  if (!hasMicrosoftAccountEntry(doc, account))
57646
57774
  return yamlText;
57647
57775
  const existing = doc.getIn(["microsoft_accounts", account, "enabled_for"]);
57648
- if (!import_yaml7.isSeq(existing))
57776
+ if (!import_yaml8.isSeq(existing))
57649
57777
  return yamlText;
57650
57778
  const seq = existing;
57651
57779
  const beforeLen = seq.items.length;
@@ -57661,16 +57789,16 @@ function disableAgentsOnMicrosoftAccount(yamlText, account, agentsToDisable) {
57661
57789
  return String(doc);
57662
57790
  }
57663
57791
  function getEnabledAgentsForMicrosoftAccount(yamlText, account) {
57664
- const doc = import_yaml7.parseDocument(yamlText);
57792
+ const doc = import_yaml8.parseDocument(yamlText);
57665
57793
  if (!hasMicrosoftAccountEntry(doc, account))
57666
57794
  return null;
57667
57795
  const existing = doc.getIn(["microsoft_accounts", account, "enabled_for"]);
57668
57796
  return readEnabledFor2(existing);
57669
57797
  }
57670
57798
  function listMicrosoftAccounts(yamlText) {
57671
- const doc = import_yaml7.parseDocument(yamlText);
57799
+ const doc = import_yaml8.parseDocument(yamlText);
57672
57800
  const accounts = doc.get("microsoft_accounts");
57673
- if (!import_yaml7.isMap(accounts))
57801
+ if (!import_yaml8.isMap(accounts))
57674
57802
  return [];
57675
57803
  const out = [];
57676
57804
  for (const item of accounts.items) {
@@ -57685,7 +57813,7 @@ function listMicrosoftAccounts(yamlText) {
57685
57813
  return out;
57686
57814
  }
57687
57815
  function removeMicrosoftAccountEntry(yamlText, account) {
57688
- const doc = import_yaml7.parseDocument(yamlText);
57816
+ const doc = import_yaml8.parseDocument(yamlText);
57689
57817
  if (!hasMicrosoftAccountEntry(doc, account))
57690
57818
  return yamlText;
57691
57819
  doc.deleteIn(["microsoft_accounts", account]);
@@ -57693,7 +57821,7 @@ function removeMicrosoftAccountEntry(yamlText, account) {
57693
57821
  return String(doc);
57694
57822
  }
57695
57823
  function readEnabledFor2(node) {
57696
- if (!import_yaml7.isSeq(node))
57824
+ if (!import_yaml8.isSeq(node))
57697
57825
  return [];
57698
57826
  const seq = node;
57699
57827
  return seq.items.map((item) => item.value ?? item).filter((v) => typeof v === "string");
@@ -57705,13 +57833,13 @@ function ensureMicrosoftAccountEntry(doc, account) {
57705
57833
  }
57706
57834
  function hasMicrosoftAccountEntry(doc, account) {
57707
57835
  const accounts = doc.get("microsoft_accounts");
57708
- if (!import_yaml7.isMap(accounts))
57836
+ if (!import_yaml8.isMap(accounts))
57709
57837
  return false;
57710
57838
  return accounts.has(account);
57711
57839
  }
57712
57840
  function pruneEmptyMap(doc, path) {
57713
57841
  const node = doc.getIn(path);
57714
- if (import_yaml7.isMap(node) && node.items.length === 0) {
57842
+ if (import_yaml8.isMap(node) && node.items.length === 0) {
57715
57843
  doc.deleteIn(path);
57716
57844
  }
57717
57845
  }
@@ -57813,7 +57941,7 @@ function registerEnable2(microsoftParent, program3) {
57813
57941
  agents = expandAllAgents2(agents, config);
57814
57942
  validateAgentSlugs(agents, config);
57815
57943
  const yamlPath = getConfigPath(program3);
57816
- const before = readFileSync24(yamlPath, "utf-8");
57944
+ const before = readFileSync25(yamlPath, "utf-8");
57817
57945
  const enabledBefore = getEnabledAgentsBefore2(before, normalizedAccount);
57818
57946
  const after = enableAgentsOnMicrosoftAccount(before, normalizedAccount, agents);
57819
57947
  if (after !== before)
@@ -57843,7 +57971,7 @@ function registerDisable2(microsoftParent, program3) {
57843
57971
  const config = getConfig(program3);
57844
57972
  agents = expandAllAgents2(agents, config);
57845
57973
  const yamlPath = getConfigPath(program3);
57846
- const before = readFileSync24(yamlPath, "utf-8");
57974
+ const before = readFileSync25(yamlPath, "utf-8");
57847
57975
  const enabledBefore = getEnabledAgentsBefore2(before, normalizedAccount);
57848
57976
  if (enabledBefore.length === 0) {
57849
57977
  console.log();
@@ -57877,7 +58005,7 @@ function registerDisable2(microsoftParent, program3) {
57877
58005
  function registerList2(microsoftParent, program3) {
57878
58006
  microsoftParent.command("list").description("List every Microsoft account configured in switchroom.yaml with its enabled_for[] agents.").option("--json", "Emit raw JSON instead of a table").action(withConfigError(async (opts) => {
57879
58007
  const yamlPath = getConfigPath(program3);
57880
- const yaml = readFileSync24(yamlPath, "utf-8");
58008
+ const yaml = readFileSync25(yamlPath, "utf-8");
57881
58009
  const accounts = listMicrosoftAccounts(yaml);
57882
58010
  if (opts.json) {
57883
58011
  console.log(JSON.stringify(accounts, null, 2));
@@ -58052,7 +58180,7 @@ function registerAccountRemove2(accountParent) {
58052
58180
  const { brokerCall: brokerCall2 } = await Promise.resolve().then(() => (init_broker_call(), exports_broker_call));
58053
58181
  const program3 = command.parent?.parent?.parent ?? command;
58054
58182
  const yamlPath = getConfigPath(program3);
58055
- const before = readFileSync24(yamlPath, "utf-8");
58183
+ const before = readFileSync25(yamlPath, "utf-8");
58056
58184
  const enabled = getEnabledAgentsForMicrosoftAccount(before, normalizedAccount);
58057
58185
  if (enabled && enabled.length > 0) {
58058
58186
  throw new Error(`Account ${normalizedAccount} is still enabled on agents: ${enabled.join(", ")}. Run 'switchroom auth microsoft disable ${normalizedAccount} all' first.`);
@@ -58236,7 +58364,7 @@ function diagnoseAuthState(claudeConfigDir) {
58236
58364
  } else if (hasCreds) {
58237
58365
  let parsed;
58238
58366
  try {
58239
- parsed = JSON.parse(readFileSync26(credsPath, "utf-8"));
58367
+ parsed = JSON.parse(readFileSync27(credsPath, "utf-8"));
58240
58368
  } catch (err) {
58241
58369
  const code = err?.code;
58242
58370
  if (code === "EACCES" || code === "EPERM") {
@@ -58404,7 +58532,7 @@ function loadCredentialsFromAgent(agentName) {
58404
58532
  }
58405
58533
  let parsed;
58406
58534
  try {
58407
- parsed = JSON.parse(readFileSync26(credsPath, "utf-8"));
58535
+ parsed = JSON.parse(readFileSync27(credsPath, "utf-8"));
58408
58536
  } catch (err) {
58409
58537
  console.error(source_default.red(` Failed to parse credentials.json: ${err.message}`));
58410
58538
  process.exit(1);
@@ -58422,7 +58550,7 @@ function loadCredentialsFromFile(path) {
58422
58550
  }
58423
58551
  let parsed;
58424
58552
  try {
58425
- parsed = JSON.parse(readFileSync26(path, "utf-8"));
58553
+ parsed = JSON.parse(readFileSync27(path, "utf-8"));
58426
58554
  } catch (err) {
58427
58555
  console.error(source_default.red(` Failed to parse ${path}: ${err.message}`));
58428
58556
  process.exit(1);
@@ -58555,7 +58683,7 @@ function registerAuthCommand(program3) {
58555
58683
  function pinAuthActiveInYaml(label, quiet = false) {
58556
58684
  try {
58557
58685
  const yamlPath = getConfigPath(program3);
58558
- const before = readFileSync26(yamlPath, "utf-8");
58686
+ const before = readFileSync27(yamlPath, "utf-8");
58559
58687
  const after = setAuthActive(before, label);
58560
58688
  if (after !== before) {
58561
58689
  let mode = 420;
@@ -58703,15 +58831,15 @@ init_loader();
58703
58831
  init_loader();
58704
58832
  init_vault();
58705
58833
  import { createInterface as createInterface3 } from "node:readline";
58706
- import { readFileSync as readFileSync35 } from "node:fs";
58834
+ import { readFileSync as readFileSync36 } from "node:fs";
58707
58835
 
58708
58836
  // src/cli/vault-sweep.ts
58709
58837
  init_source();
58710
58838
  init_loader();
58711
58839
  init_vault();
58712
58840
  init_hindsight();
58713
- import { readFileSync as readFileSync27, writeFileSync as writeFileSync17, copyFileSync as copyFileSync6, existsSync as existsSync32, readdirSync as readdirSync15, statSync as statSync17 } from "node:fs";
58714
- import { execFileSync as execFileSync14 } from "node:child_process";
58841
+ import { readFileSync as readFileSync28, writeFileSync as writeFileSync17, copyFileSync as copyFileSync6, existsSync as existsSync32, readdirSync as readdirSync15, statSync as statSync17 } from "node:fs";
58842
+ import { execFileSync as execFileSync15 } from "node:child_process";
58715
58843
  import { join as join24 } from "node:path";
58716
58844
  import { homedir as homedir11 } from "node:os";
58717
58845
  function getVaultPath2(configPath) {
@@ -58771,7 +58899,7 @@ function findTelegramHistoryDb() {
58771
58899
  function scrubJsonl(path, values, dryRun) {
58772
58900
  let content;
58773
58901
  try {
58774
- content = readFileSync27(path, "utf8");
58902
+ content = readFileSync28(path, "utf8");
58775
58903
  } catch {
58776
58904
  return { target: path, matches: 0, modified: false };
58777
58905
  }
@@ -59049,7 +59177,7 @@ function registerVaultSweep(vault, program3) {
59049
59177
  function scrubSqlite(path, values, dryRun) {
59050
59178
  let hasSqlite = true;
59051
59179
  try {
59052
- execFileSync14("sqlite3", ["-version"], { timeout: 2000, stdio: "ignore" });
59180
+ execFileSync15("sqlite3", ["-version"], { timeout: 2000, stdio: "ignore" });
59053
59181
  } catch {
59054
59182
  hasSqlite = false;
59055
59183
  }
@@ -59061,7 +59189,7 @@ function scrubSqlite(path, values, dryRun) {
59061
59189
  for (const { value } of values) {
59062
59190
  const esc = value.replace(/'/g, "''");
59063
59191
  try {
59064
- const out = execFileSync14("sqlite3", [path, `SELECT COUNT(*) FROM messages WHERE text LIKE '%${esc}%'`], { encoding: "utf8", timeout: 1e4 });
59192
+ const out = execFileSync15("sqlite3", [path, `SELECT COUNT(*) FROM messages WHERE text LIKE '%${esc}%'`], { encoding: "utf8", timeout: 1e4 });
59065
59193
  const n = parseInt(out.trim(), 10);
59066
59194
  if (!Number.isNaN(n))
59067
59195
  matches += n;
@@ -59075,7 +59203,7 @@ function scrubSqlite(path, values, dryRun) {
59075
59203
  for (const { key, value } of values) {
59076
59204
  const esc = value.replace(/'/g, "''");
59077
59205
  const replacement = `vault:${key}`.replace(/'/g, "''");
59078
- execFileSync14("sqlite3", [path, `UPDATE messages SET text = replace(text, '${esc}', '${replacement}')`], { timeout: 15000 });
59206
+ execFileSync15("sqlite3", [path, `UPDATE messages SET text = replace(text, '${esc}', '${replacement}')`], { timeout: 15000 });
59079
59207
  }
59080
59208
  return { target: path, matches, modified: true };
59081
59209
  } catch (err) {
@@ -59113,14 +59241,14 @@ function suggestVaultKeys(requested, available, max = 3) {
59113
59241
  init_loader();
59114
59242
  init_loader();
59115
59243
  init_client();
59116
- import { readFileSync as readFileSync32, existsSync as existsSync36, unlinkSync as unlinkSync9 } from "node:fs";
59244
+ import { readFileSync as readFileSync33, existsSync as existsSync36, unlinkSync as unlinkSync9 } from "node:fs";
59117
59245
  import { spawn as spawn4 } from "node:child_process";
59118
59246
 
59119
59247
  // src/vault/broker/server.ts
59120
59248
  init_compose();
59121
59249
  init_vault();
59122
59250
  import * as net3 from "node:net";
59123
- import { mkdirSync as mkdirSync22, chmodSync as chmodSync7, chownSync as chownSync2, existsSync as existsSync35, readFileSync as readFileSync30, readdirSync as readdirSync16, statSync as statSync19, unlinkSync as unlinkSync8, writeFileSync as writeFileSync19, renameSync as renameSync10 } from "node:fs";
59251
+ 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";
59124
59252
  import { dirname as dirname6, resolve as resolve26, basename as basename4 } from "node:path";
59125
59253
  import * as os4 from "node:os";
59126
59254
  import * as path3 from "node:path";
@@ -59136,7 +59264,7 @@ import {
59136
59264
  mkdirSync as mkdirSync19,
59137
59265
  openSync as openSync6,
59138
59266
  closeSync as closeSync6,
59139
- readFileSync as readFileSync28,
59267
+ readFileSync as readFileSync29,
59140
59268
  renameSync as renameSync9,
59141
59269
  statSync as statSync18,
59142
59270
  symlinkSync as symlinkSync3,
@@ -59292,7 +59420,7 @@ function lstatSyncOrNull(path) {
59292
59420
  }
59293
59421
  }
59294
59422
  function sha256File(path) {
59295
- const data = readFileSync28(path);
59423
+ const data = readFileSync29(path);
59296
59424
  return createHash5("sha256").update(data).digest("hex");
59297
59425
  }
59298
59426
  function atomicReplaceWithSymlink(target, linkTarget) {
@@ -59327,7 +59455,7 @@ init_loader();
59327
59455
 
59328
59456
  // src/vault/auto-unlock.ts
59329
59457
  import { createHmac, randomBytes as randomBytes6, createCipheriv as createCipheriv2, createDecipheriv as createDecipheriv2 } from "node:crypto";
59330
- import { chmodSync as chmodSync5, existsSync as existsSync34, mkdirSync as mkdirSync20, readFileSync as readFileSync29, writeFileSync as writeFileSync18 } from "node:fs";
59458
+ import { chmodSync as chmodSync5, existsSync as existsSync34, mkdirSync as mkdirSync20, readFileSync as readFileSync30, writeFileSync as writeFileSync18 } from "node:fs";
59331
59459
  import { dirname as dirname4 } from "node:path";
59332
59460
  var FORMAT_VERSION = 1;
59333
59461
  var SALT_LEN = 16;
@@ -59363,7 +59491,7 @@ function readMachineId() {
59363
59491
  }
59364
59492
  for (const path of [MACHINE_ID_PRIMARY, MACHINE_ID_FALLBACK]) {
59365
59493
  try {
59366
- const id = readFileSync29(path, "utf8").trim();
59494
+ const id = readFileSync30(path, "utf8").trim();
59367
59495
  if (id.length > 0)
59368
59496
  return id;
59369
59497
  } catch {}
@@ -59427,7 +59555,7 @@ function readAutoUnlockFile(filePath) {
59427
59555
  }
59428
59556
  let blob;
59429
59557
  try {
59430
- blob = readFileSync29(filePath);
59558
+ blob = readFileSync30(filePath);
59431
59559
  } catch {
59432
59560
  throw new AutoUnlockDecryptError("io");
59433
59561
  }
@@ -63284,7 +63412,7 @@ class VaultBroker {
63284
63412
  const credPath = `${dir}/vault-passphrase`;
63285
63413
  let passphrase;
63286
63414
  try {
63287
- passphrase = readFileSync30(credPath, "utf8").replace(/\n+$/, "");
63415
+ passphrase = readFileSync31(credPath, "utf8").replace(/\n+$/, "");
63288
63416
  } catch (err) {
63289
63417
  const code = err.code;
63290
63418
  if (code === "ENOENT") {
@@ -63435,9 +63563,9 @@ init_vault();
63435
63563
  // src/cli/vault-auto-unlock.ts
63436
63564
  init_loader();
63437
63565
  init_client();
63438
- var import_yaml9 = __toESM(require_dist(), 1);
63566
+ var import_yaml10 = __toESM(require_dist(), 1);
63439
63567
  import { spawnSync as spawnSync3 } from "node:child_process";
63440
- import { readFileSync as readFileSync31, writeFileSync as writeFileSync20 } from "node:fs";
63568
+ import { readFileSync as readFileSync32, writeFileSync as writeFileSync20 } from "node:fs";
63441
63569
  import { homedir as homedir16 } from "node:os";
63442
63570
  import { join as join31 } from "node:path";
63443
63571
  class EncryptFailedError extends Error {
@@ -63467,8 +63595,8 @@ function encryptCredential(passphrase, credPath) {
63467
63595
  }
63468
63596
  }
63469
63597
  function setVaultBrokerAutoUnlock(configPath, value) {
63470
- const raw = readFileSync31(configPath, "utf-8");
63471
- const doc = import_yaml9.default.parseDocument(raw);
63598
+ const raw = readFileSync32(configPath, "utf-8");
63599
+ const doc = import_yaml10.default.parseDocument(raw);
63472
63600
  doc.setIn(["vault", "broker", "autoUnlock"], value);
63473
63601
  writeFileSync20(configPath, doc.toString(), "utf-8");
63474
63602
  }
@@ -63662,7 +63790,7 @@ function registerVaultBrokerCommand(vaultCmd, program3) {
63662
63790
  console.error("vault-broker PID file not found \u2014 is the daemon running?");
63663
63791
  process.exit(1);
63664
63792
  }
63665
- const pid = parseInt(readFileSync32(pidPath, "utf8").trim(), 10);
63793
+ const pid = parseInt(readFileSync33(pidPath, "utf8").trim(), 10);
63666
63794
  if (isNaN(pid) || pid <= 0) {
63667
63795
  console.error("Invalid PID file contents");
63668
63796
  process.exit(1);
@@ -64035,7 +64163,7 @@ Vault Doctor`));
64035
64163
 
64036
64164
  // src/cli/vault-audit.ts
64037
64165
  init_source();
64038
- import { existsSync as existsSync38, readFileSync as readFileSync33 } from "node:fs";
64166
+ import { existsSync as existsSync38, readFileSync as readFileSync34 } from "node:fs";
64039
64167
 
64040
64168
  // src/vault/audit-reader.ts
64041
64169
  function parseAuditLine(line) {
@@ -64114,7 +64242,7 @@ function registerVaultAuditCommand(vault, _program) {
64114
64242
  The log is created when the vault broker handles its first request.`));
64115
64243
  process.exit(0);
64116
64244
  }
64117
- const raw = readFileSync33(logPath, "utf-8");
64245
+ const raw = readFileSync34(logPath, "utf-8");
64118
64246
  const rawLines = raw.split(`
64119
64247
  `);
64120
64248
  const limit = Math.max(1, parseInt(opts.tail ?? "50", 10) || 50);
@@ -64324,7 +64452,7 @@ import {
64324
64452
  mkdirSync as mkdirSync23,
64325
64453
  openSync as openSync9,
64326
64454
  readdirSync as readdirSync17,
64327
- readFileSync as readFileSync34,
64455
+ readFileSync as readFileSync35,
64328
64456
  renameSync as renameSync11,
64329
64457
  statSync as statSync20,
64330
64458
  symlinkSync as symlinkSync4,
@@ -64371,7 +64499,7 @@ function parseBackupFilename(name) {
64371
64499
  function validateVaultEnvelopeFile(path4) {
64372
64500
  let buf;
64373
64501
  try {
64374
- buf = readFileSync34(path4);
64502
+ buf = readFileSync35(path4);
64375
64503
  } catch (err) {
64376
64504
  return `cannot read ${path4}: ${err.message}`;
64377
64505
  }
@@ -64443,7 +64571,7 @@ function listBackupFiles(dir) {
64443
64571
  }
64444
64572
  function sha256OfFile(path4) {
64445
64573
  const h = createHash8("sha256");
64446
- h.update(readFileSync34(path4));
64574
+ h.update(readFileSync35(path4));
64447
64575
  return h.digest("hex");
64448
64576
  }
64449
64577
  function backupVault(opts) {
@@ -64463,7 +64591,7 @@ function backupVault(opts) {
64463
64591
  const fullPath = join33(opts.destDir, filename);
64464
64592
  const tmpName = `.tmp.${process.pid}.${randomBytes10(4).toString("hex")}`;
64465
64593
  const tmpPath = join33(opts.destDir, tmpName);
64466
- const src = readFileSync34(opts.vaultPath);
64594
+ const src = readFileSync35(opts.vaultPath);
64467
64595
  const fd = openSync9(tmpPath, "wx", 384);
64468
64596
  try {
64469
64597
  writeSync5(fd, src);
@@ -64838,7 +64966,7 @@ function registerVaultCommand(program3) {
64838
64966
  let isBinaryFile = false;
64839
64967
  if (opts.file) {
64840
64968
  try {
64841
- const buf = readFileSync35(resolvePath(opts.file));
64969
+ const buf = readFileSync36(resolvePath(opts.file));
64842
64970
  const asUtf8 = buf.toString("utf8");
64843
64971
  if (Buffer.compare(buf, Buffer.from(asUtf8, "utf8")) === 0) {
64844
64972
  value = asUtf8;
@@ -65182,7 +65310,7 @@ Push passphrase to broker for future requests? [Y/n]: `);
65182
65310
 
65183
65311
  // src/cli/telegram.ts
65184
65312
  init_source();
65185
- import { existsSync as existsSync41, readFileSync as readFileSync36, writeFileSync as writeFileSync21 } from "node:fs";
65313
+ import { existsSync as existsSync41, readFileSync as readFileSync37, writeFileSync as writeFileSync21 } from "node:fs";
65186
65314
  import { join as join35 } from "node:path";
65187
65315
 
65188
65316
  // src/web/webhook-dispatch.ts
@@ -65286,15 +65414,15 @@ init_paths();
65286
65414
  import { createInterface as createInterface4 } from "node:readline";
65287
65415
 
65288
65416
  // src/cli/telegram-yaml.ts
65289
- var import_yaml10 = __toESM(require_dist(), 1);
65417
+ var import_yaml11 = __toESM(require_dist(), 1);
65290
65418
  function setTelegramFeature(yamlText, agentName, feature, value) {
65291
- const doc = import_yaml10.parseDocument(yamlText);
65419
+ const doc = import_yaml11.parseDocument(yamlText);
65292
65420
  ensureAgent(doc, agentName);
65293
65421
  doc.setIn(["agents", agentName, "channels", "telegram", feature], value);
65294
65422
  return String(doc);
65295
65423
  }
65296
65424
  function removeTelegramFeature(yamlText, agentName, feature) {
65297
- const doc = import_yaml10.parseDocument(yamlText);
65425
+ const doc = import_yaml11.parseDocument(yamlText);
65298
65426
  if (!hasAgent(doc, agentName))
65299
65427
  return yamlText;
65300
65428
  if (!doc.hasIn(["agents", agentName, "channels", "telegram", feature])) {
@@ -65312,21 +65440,21 @@ function ensureAgent(doc, agentName) {
65312
65440
  }
65313
65441
  function hasAgent(doc, agentName) {
65314
65442
  const agents = doc.get("agents");
65315
- if (!import_yaml10.isMap(agents))
65443
+ if (!import_yaml11.isMap(agents))
65316
65444
  return false;
65317
65445
  return agents.has(agentName);
65318
65446
  }
65319
65447
  function pruneEmptyMap2(doc, path4) {
65320
65448
  const node = doc.getIn(path4);
65321
- if (import_yaml10.isMap(node) && node.items.length === 0) {
65449
+ if (import_yaml11.isMap(node) && node.items.length === 0) {
65322
65450
  doc.deleteIn(path4);
65323
65451
  }
65324
65452
  }
65325
65453
  function addWebhookSource(yamlText, agentName, source) {
65326
- const doc = import_yaml10.parseDocument(yamlText);
65454
+ const doc = import_yaml11.parseDocument(yamlText);
65327
65455
  ensureAgent(doc, agentName);
65328
65456
  const existing = doc.getIn(["agents", agentName, "channels", "telegram", "webhook_sources"]);
65329
- if (import_yaml10.isSeq(existing)) {
65457
+ if (import_yaml11.isSeq(existing)) {
65330
65458
  const seq = existing;
65331
65459
  for (const item of seq.items) {
65332
65460
  const v = item.value ?? item;
@@ -65340,11 +65468,11 @@ function addWebhookSource(yamlText, agentName, source) {
65340
65468
  return String(doc);
65341
65469
  }
65342
65470
  function removeWebhookSource(yamlText, agentName, source) {
65343
- const doc = import_yaml10.parseDocument(yamlText);
65471
+ const doc = import_yaml11.parseDocument(yamlText);
65344
65472
  if (!hasAgent(doc, agentName))
65345
65473
  return yamlText;
65346
65474
  const existing = doc.getIn(["agents", agentName, "channels", "telegram", "webhook_sources"]);
65347
- if (!import_yaml10.isSeq(existing))
65475
+ if (!import_yaml11.isSeq(existing))
65348
65476
  return yamlText;
65349
65477
  const seq = existing;
65350
65478
  const beforeLen = seq.items.length;
@@ -65613,7 +65741,7 @@ function registerDisableVerb(tg, program3) {
65613
65741
  }
65614
65742
  async function applyYamlEdit(program3, agent, feature, value, dryRun) {
65615
65743
  const path4 = getConfigPath(program3);
65616
- const before = readFileSync36(path4, "utf-8");
65744
+ const before = readFileSync37(path4, "utf-8");
65617
65745
  let after;
65618
65746
  try {
65619
65747
  after = setTelegramFeature(before, agent, feature, value);
@@ -65628,7 +65756,7 @@ async function applyYamlEdit(program3, agent, feature, value, dryRun) {
65628
65756
  }
65629
65757
  async function applyYamlRemove(program3, agent, feature, dryRun) {
65630
65758
  const path4 = getConfigPath(program3);
65631
- const before = readFileSync36(path4, "utf-8");
65759
+ const before = readFileSync37(path4, "utf-8");
65632
65760
  const after = removeTelegramFeature(before, agent, feature);
65633
65761
  if (before === after) {
65634
65762
  console.log(source_default.yellow(`No change \u2014 ${feature.replace("_", "-")} is not set for agent '${agent}'.`));
@@ -65677,7 +65805,7 @@ function fail(msg) {
65677
65805
  }
65678
65806
  async function applyYamlAddWebhook(program3, agent, source, dryRun) {
65679
65807
  const path4 = getConfigPath(program3);
65680
- const before = readFileSync36(path4, "utf-8");
65808
+ const before = readFileSync37(path4, "utf-8");
65681
65809
  let after;
65682
65810
  try {
65683
65811
  after = addWebhookSource(before, agent, source);
@@ -65697,7 +65825,7 @@ async function applyYamlAddWebhook(program3, agent, source, dryRun) {
65697
65825
  }
65698
65826
  async function applyYamlRemoveWebhook(program3, agent, source, dryRun) {
65699
65827
  const path4 = getConfigPath(program3);
65700
- const before = readFileSync36(path4, "utf-8");
65828
+ const before = readFileSync37(path4, "utf-8");
65701
65829
  const after = removeWebhookSource(before, agent, source);
65702
65830
  if (before === after) {
65703
65831
  console.log(source_default.yellow(`No change \u2014 webhook source '${source}' is not currently enabled for agent '${agent}'.`));
@@ -65754,7 +65882,7 @@ function registerDispatchVerb(tg, _program) {
65754
65882
  }
65755
65883
  let payload;
65756
65884
  try {
65757
- payload = JSON.parse(readFileSync36(opts.payload, "utf-8"));
65885
+ payload = JSON.parse(readFileSync37(opts.payload, "utf-8"));
65758
65886
  } catch (err) {
65759
65887
  fail(`Could not read payload file '${opts.payload}': ${err.message}`);
65760
65888
  }
@@ -65875,7 +66003,7 @@ function reflectAcrossAgents(config) {
65875
66003
  init_helpers();
65876
66004
 
65877
66005
  // src/setup/hindsight.ts
65878
- import { execFileSync as execFileSync15 } from "node:child_process";
66006
+ import { execFileSync as execFileSync16 } from "node:child_process";
65879
66007
  import { createServer as createServer4 } from "node:net";
65880
66008
  var HINDSIGHT_DEFAULT_API_PORT = 8888;
65881
66009
  var HINDSIGHT_DEFAULT_UI_PORT = 9999;
@@ -65930,7 +66058,7 @@ async function pickHindsightPorts() {
65930
66058
  }
65931
66059
  function isDockerAvailable() {
65932
66060
  try {
65933
- execFileSync15("docker", ["--version"], { stdio: "pipe" });
66061
+ execFileSync16("docker", ["--version"], { stdio: "pipe" });
65934
66062
  return true;
65935
66063
  } catch {
65936
66064
  return false;
@@ -65938,7 +66066,7 @@ function isDockerAvailable() {
65938
66066
  }
65939
66067
  function isHindsightRunning() {
65940
66068
  try {
65941
- const output = execFileSync15("docker", ["ps", "--filter", "name=switchroom-hindsight", "--format", "{{.Status}}"], { stdio: "pipe", encoding: "utf-8" });
66069
+ const output = execFileSync16("docker", ["ps", "--filter", "name=switchroom-hindsight", "--format", "{{.Status}}"], { stdio: "pipe", encoding: "utf-8" });
65942
66070
  return output.trim().length > 0;
65943
66071
  } catch {
65944
66072
  return false;
@@ -65946,7 +66074,7 @@ function isHindsightRunning() {
65946
66074
  }
65947
66075
  function isHindsightContainerExists() {
65948
66076
  try {
65949
- const output = execFileSync15("docker", ["ps", "-a", "--filter", "name=switchroom-hindsight", "--format", "{{.Names}}"], { stdio: "pipe", encoding: "utf-8" });
66077
+ const output = execFileSync16("docker", ["ps", "-a", "--filter", "name=switchroom-hindsight", "--format", "{{.Names}}"], { stdio: "pipe", encoding: "utf-8" });
65950
66078
  return output.trim().length > 0;
65951
66079
  } catch {
65952
66080
  return false;
@@ -65996,19 +66124,19 @@ function startHindsight(ports) {
65996
66124
  ...envArgs,
65997
66125
  HINDSIGHT_IMAGE
65998
66126
  ];
65999
- execFileSync15("docker", args, { stdio: "pipe" });
66127
+ execFileSync16("docker", args, { stdio: "pipe" });
66000
66128
  }
66001
66129
  function stopHindsight() {
66002
66130
  try {
66003
- execFileSync15("docker", ["stop", "switchroom-hindsight"], { stdio: "pipe" });
66131
+ execFileSync16("docker", ["stop", "switchroom-hindsight"], { stdio: "pipe" });
66004
66132
  } catch {}
66005
66133
  try {
66006
- execFileSync15("docker", ["rm", "switchroom-hindsight"], { stdio: "pipe" });
66134
+ execFileSync16("docker", ["rm", "switchroom-hindsight"], { stdio: "pipe" });
66007
66135
  } catch {}
66008
66136
  }
66009
66137
  function getHindsightStatus() {
66010
66138
  try {
66011
- const output = execFileSync15("docker", ["ps", "-a", "--filter", "name=switchroom-hindsight", "--format", "{{.Status}}"], { stdio: "pipe", encoding: "utf-8" });
66139
+ const output = execFileSync16("docker", ["ps", "-a", "--filter", "name=switchroom-hindsight", "--format", "{{.Status}}"], { stdio: "pipe", encoding: "utf-8" });
66012
66140
  const status = output.trim();
66013
66141
  return status.length > 0 ? status : null;
66014
66142
  } catch {
@@ -66106,8 +66234,8 @@ async function ensureHindsightConsumer(configPath, account, uid = HINDSIGHT_DEFA
66106
66234
 
66107
66235
  // src/cli/memory.ts
66108
66236
  init_loader();
66109
- var import_yaml11 = __toESM(require_dist(), 1);
66110
- import { existsSync as existsSync42, readFileSync as readFileSync37, writeFileSync as writeFileSync22 } from "node:fs";
66237
+ var import_yaml12 = __toESM(require_dist(), 1);
66238
+ import { existsSync as existsSync42, readFileSync as readFileSync38, writeFileSync as writeFileSync22 } from "node:fs";
66111
66239
  import { join as join36 } from "node:path";
66112
66240
  function readRecallLog(agentDir, limit) {
66113
66241
  const path4 = join36(agentDir, ".claude", "plugins", "data", "hindsight-memory-inline", "state", "recall_log.jsonl");
@@ -66115,7 +66243,7 @@ function readRecallLog(agentDir, limit) {
66115
66243
  return [];
66116
66244
  let raw;
66117
66245
  try {
66118
- raw = readFileSync37(path4, "utf-8");
66246
+ raw = readFileSync38(path4, "utf-8");
66119
66247
  } catch {
66120
66248
  return [];
66121
66249
  }
@@ -66310,8 +66438,8 @@ Cross-agent reflection plan
66310
66438
  const configPath = getConfigPath(program3);
66311
66439
  try {
66312
66440
  if (existsSync42(configPath)) {
66313
- const raw = readFileSync37(configPath, "utf-8");
66314
- const doc = import_yaml11.default.parseDocument(raw);
66441
+ const raw = readFileSync38(configPath, "utf-8");
66442
+ const doc = import_yaml12.default.parseDocument(raw);
66315
66443
  if (!doc.has("memory")) {
66316
66444
  doc.set("memory", { backend: "hindsight", shared_collection: "shared", config: { provider, url } });
66317
66445
  } else {
@@ -66417,7 +66545,7 @@ init_source();
66417
66545
  init_merge();
66418
66546
  init_lifecycle();
66419
66547
  import {
66420
- readFileSync as readFileSync42,
66548
+ readFileSync as readFileSync43,
66421
66549
  existsSync as existsSync47,
66422
66550
  realpathSync as realpathSync3,
66423
66551
  mkdirSync as mkdirSync27,
@@ -66436,7 +66564,7 @@ init_lifecycle();
66436
66564
  init_manager();
66437
66565
  init_hindsight();
66438
66566
  import { spawnSync as spawnSync4 } from "node:child_process";
66439
- import { existsSync as existsSync44, readFileSync as readFileSync39 } from "node:fs";
66567
+ import { existsSync as existsSync44, readFileSync as readFileSync40 } from "node:fs";
66440
66568
  import { resolve as resolve27 } from "node:path";
66441
66569
  init_audit_reader();
66442
66570
 
@@ -70940,7 +71068,7 @@ init_paths();
70940
71068
  import {
70941
71069
  existsSync as existsSync43,
70942
71070
  mkdirSync as mkdirSync24,
70943
- readFileSync as readFileSync38,
71071
+ readFileSync as readFileSync39,
70944
71072
  writeFileSync as writeFileSync23
70945
71073
  } from "node:fs";
70946
71074
  import { dirname as dirname8 } from "node:path";
@@ -70961,7 +71089,7 @@ function getDistinctId() {
70961
71089
  const path4 = resolveStatePath("analytics-id");
70962
71090
  try {
70963
71091
  if (existsSync43(path4)) {
70964
- const existing = readFileSync38(path4, "utf-8").trim();
71092
+ const existing = readFileSync39(path4, "utf-8").trim();
70965
71093
  if (existing) {
70966
71094
  cachedDistinctId = existing;
70967
71095
  return existing;
@@ -71537,7 +71665,7 @@ async function handleGetSystemHealth(home2) {
71537
71665
  const logPath = defaultAuditLogPath2(home2);
71538
71666
  if (existsSync44(logPath)) {
71539
71667
  hostd.auditLogPresent = true;
71540
- const raw = readFileSync39(logPath, "utf-8");
71668
+ const raw = readFileSync40(logPath, "utf-8");
71541
71669
  hostd.recent = readAndFilter(raw, {}, 10);
71542
71670
  }
71543
71671
  } catch (err) {
@@ -71616,7 +71744,7 @@ async function handleGetApprovals() {
71616
71744
  }
71617
71745
 
71618
71746
  // src/web/webhook-handler.ts
71619
- import { appendFileSync as appendFileSync3, existsSync as existsSync46, mkdirSync as mkdirSync26, readFileSync as readFileSync41, writeFileSync as writeFileSync24 } from "fs";
71747
+ import { appendFileSync as appendFileSync3, existsSync as existsSync46, mkdirSync as mkdirSync26, readFileSync as readFileSync42, writeFileSync as writeFileSync24 } from "fs";
71620
71748
  import { join as join40 } from "path";
71621
71749
  import { homedir as homedir21 } from "os";
71622
71750
 
@@ -71768,7 +71896,7 @@ function forwardToGateway(socketPath, req, opts = {}) {
71768
71896
  }
71769
71897
 
71770
71898
  // src/web/webhook-edge.ts
71771
- import { existsSync as existsSync45, readFileSync as readFileSync40 } from "fs";
71899
+ import { existsSync as existsSync45, readFileSync as readFileSync41 } from "fs";
71772
71900
  import { join as join39 } from "path";
71773
71901
  import { homedir as homedir20 } from "os";
71774
71902
  import { timingSafeEqual as timingSafeEqual2 } from "crypto";
@@ -71781,7 +71909,7 @@ function loadEdgeSecret(path4) {
71781
71909
  try {
71782
71910
  if (!existsSync45(p))
71783
71911
  return null;
71784
- const raw = readFileSync40(p, "utf-8").trim();
71912
+ const raw = readFileSync41(p, "utf-8").trim();
71785
71913
  return raw.length > 0 ? raw : null;
71786
71914
  } catch {
71787
71915
  return null;
@@ -71815,7 +71943,7 @@ function loadDedupFile(path4) {
71815
71943
  try {
71816
71944
  if (!existsSync46(path4))
71817
71945
  return {};
71818
- const raw = JSON.parse(readFileSync41(path4, "utf-8"));
71946
+ const raw = JSON.parse(readFileSync42(path4, "utf-8"));
71819
71947
  return typeof raw.deliveries === "object" && raw.deliveries !== null ? raw.deliveries : {};
71820
71948
  } catch {
71821
71949
  return {};
@@ -72095,7 +72223,7 @@ function resolveWebToken() {
72095
72223
  const home2 = process.env.HOME ?? homedir22();
72096
72224
  const tokenPath = join41(home2, ".switchroom", "web-token");
72097
72225
  if (existsSync47(tokenPath)) {
72098
- const existing = readFileSync42(tokenPath, "utf8").trim();
72226
+ const existing = readFileSync43(tokenPath, "utf8").trim();
72099
72227
  if (existing.length > 0)
72100
72228
  return existing;
72101
72229
  }
@@ -72112,7 +72240,7 @@ function resolveWebToken() {
72112
72240
  return token;
72113
72241
  } catch (err) {
72114
72242
  if (err.code === "EEXIST") {
72115
- const existing = readFileSync42(tokenPath, "utf8").trim();
72243
+ const existing = readFileSync43(tokenPath, "utf8").trim();
72116
72244
  if (existing.length > 0)
72117
72245
  return existing;
72118
72246
  }
@@ -72182,7 +72310,7 @@ function loadWebhookSecrets() {
72182
72310
  if (!existsSync47(path4))
72183
72311
  return {};
72184
72312
  try {
72185
- const parsed = JSON.parse(readFileSync42(path4, "utf-8"));
72313
+ const parsed = JSON.parse(readFileSync43(path4, "utf-8"));
72186
72314
  return parsed && typeof parsed === "object" ? parsed : {};
72187
72315
  } catch (err) {
72188
72316
  process.stderr.write(`webhook-ingest: failed to parse ${path4}: ${err.message} \u2014 webhooks will return 401 until fixed
@@ -72457,7 +72585,7 @@ function startWebServer(config, port, hostname = "127.0.0.1", configPath) {
72457
72585
  }
72458
72586
  const ext = extname(realFullPath);
72459
72587
  const contentType = MIME_TYPES[ext] ?? "application/octet-stream";
72460
- const content = readFileSync42(realFullPath);
72588
+ const content = readFileSync43(realFullPath);
72461
72589
  return new Response(content, {
72462
72590
  headers: { "Content-Type": contentType }
72463
72591
  });
@@ -72591,26 +72719,26 @@ Starting Switchroom dashboard...
72591
72719
  // src/cli/setup.ts
72592
72720
  init_source();
72593
72721
  init_loader();
72594
- import { existsSync as existsSync48, copyFileSync as copyFileSync8, readFileSync as readFileSync43, writeFileSync as writeFileSync25, mkdirSync as mkdirSync28 } from "node:fs";
72722
+ import { existsSync as existsSync48, copyFileSync as copyFileSync8, readFileSync as readFileSync44, writeFileSync as writeFileSync25, mkdirSync as mkdirSync28 } from "node:fs";
72595
72723
  import { resolve as resolve29, dirname as dirname10 } from "node:path";
72596
72724
  init_vault();
72597
72725
  init_manager();
72598
72726
 
72599
72727
  // src/cli/setup-posture-rewrite.ts
72600
- var import_yaml12 = __toESM(require_dist(), 1);
72728
+ var import_yaml13 = __toESM(require_dist(), 1);
72601
72729
  function insertVaultBrokerApprovalAuth(source, value = "telegram-id") {
72602
72730
  let doc;
72603
72731
  try {
72604
- doc = import_yaml12.default.parseDocument(source);
72732
+ doc = import_yaml13.default.parseDocument(source);
72605
72733
  } catch {
72606
72734
  return { kind: "not-found" };
72607
72735
  }
72608
72736
  const vault = doc.get("vault");
72609
- if (!vault || !import_yaml12.default.isMap(vault)) {
72737
+ if (!vault || !import_yaml13.default.isMap(vault)) {
72610
72738
  return { kind: "not-found" };
72611
72739
  }
72612
72740
  const broker = vault.get("broker");
72613
- if (!broker || !import_yaml12.default.isMap(broker)) {
72741
+ if (!broker || !import_yaml13.default.isMap(broker)) {
72614
72742
  return { kind: "not-found" };
72615
72743
  }
72616
72744
  if (broker.has("approvalAuth")) {
@@ -72661,7 +72789,7 @@ ${childIndent}approvalAuth: ${value}`;
72661
72789
  }
72662
72790
 
72663
72791
  // src/cli/supergroup-setup-yaml.ts
72664
- var import_yaml13 = __toESM(require_dist(), 1);
72792
+ var import_yaml14 = __toESM(require_dist(), 1);
72665
72793
  function isValidSupergroupChatId(value) {
72666
72794
  return /^-\d+$/.test(value);
72667
72795
  }
@@ -72669,23 +72797,23 @@ function setAgentSupergroupChatId(yamlText, agentName, chatId) {
72669
72797
  if (!isValidSupergroupChatId(chatId)) {
72670
72798
  throw new Error(`setAgentSupergroupChatId: chat_id must be a negative integer string (got "${chatId}")`);
72671
72799
  }
72672
- const doc = import_yaml13.parseDocument(yamlText);
72800
+ const doc = import_yaml14.parseDocument(yamlText);
72673
72801
  const root = doc.contents;
72674
- if (!import_yaml13.isMap(root)) {
72802
+ if (!import_yaml14.isMap(root)) {
72675
72803
  throw new Error("setAgentSupergroupChatId: YAML root is not a map");
72676
72804
  }
72677
72805
  const agents = root.get("agents", true);
72678
- if (!import_yaml13.isMap(agents)) {
72806
+ if (!import_yaml14.isMap(agents)) {
72679
72807
  throw new Error("setAgentSupergroupChatId: config has no `agents:` map");
72680
72808
  }
72681
72809
  const agent = agents.get(agentName, true);
72682
- if (!import_yaml13.isMap(agent)) {
72810
+ if (!import_yaml14.isMap(agent)) {
72683
72811
  throw new Error(`setAgentSupergroupChatId: agent "${agentName}" not found in config`);
72684
72812
  }
72685
72813
  const channels = agent.get("channels", true);
72686
- if (import_yaml13.isMap(channels)) {
72814
+ if (import_yaml14.isMap(channels)) {
72687
72815
  const telegram = channels.get("telegram", true);
72688
- if (import_yaml13.isMap(telegram)) {
72816
+ if (import_yaml14.isMap(telegram)) {
72689
72817
  if (telegram.get("chat_id") === chatId)
72690
72818
  return yamlText;
72691
72819
  telegram.set("chat_id", chatId);
@@ -73320,7 +73448,7 @@ async function stepAutoUnlock(config, switchroomConfigPath, nonInteractive) {
73320
73448
  try {
73321
73449
  const yamlPath = existsSync48(resolve29(process.cwd(), "switchroom.yaml")) ? resolve29(process.cwd(), "switchroom.yaml") : resolve29(process.cwd(), "switchroom.yml");
73322
73450
  if (existsSync48(yamlPath)) {
73323
- const content = readFileSync43(yamlPath, "utf-8");
73451
+ const content = readFileSync44(yamlPath, "utf-8");
73324
73452
  const result = insertVaultBrokerApprovalAuth(content, "telegram-id");
73325
73453
  if (result.kind === "rewritten") {
73326
73454
  writeFileSync25(yamlPath, result.content, "utf-8");
@@ -73355,7 +73483,7 @@ async function stepDangerousMode(config, nonInteractive) {
73355
73483
  ];
73356
73484
  for (const configPath of configPaths) {
73357
73485
  if (existsSync48(configPath)) {
73358
- let content = readFileSync43(configPath, "utf-8");
73486
+ let content = readFileSync44(configPath, "utf-8");
73359
73487
  const agentNames = Object.keys(config.agents);
73360
73488
  for (const name of agentNames) {
73361
73489
  const agentPattern = new RegExp(`(^ ${name}:\\s*\\n)`, "m");
@@ -73465,9 +73593,9 @@ async function stepVerification(config, nonInteractive) {
73465
73593
  Start ${source_default.cyan(firstName)} now?`, false);
73466
73594
  if (startNow) {
73467
73595
  try {
73468
- const { execFileSync: execFileSync16 } = await import("node:child_process");
73596
+ const { execFileSync: execFileSync17 } = await import("node:child_process");
73469
73597
  console.log(source_default.gray(` Starting ${firstName}...`));
73470
- execFileSync16("switchroom", ["agent", "start", firstName], { stdio: "inherit" });
73598
+ execFileSync17("switchroom", ["agent", "start", firstName], { stdio: "inherit" });
73471
73599
  console.log(source_default.green(` ${STEP_DONE} Agent started`));
73472
73600
  } catch {
73473
73601
  console.log(source_default.yellow(` Could not start automatically. Run: switchroom agent start ${firstName}`));
@@ -73484,7 +73612,7 @@ init_doctor();
73484
73612
  init_source();
73485
73613
  init_loader();
73486
73614
  init_lifecycle();
73487
- import { cpSync as cpSync2, existsSync as existsSync55, mkdirSync as mkdirSync30, readFileSync as readFileSync48, realpathSync as realpathSync5, rmSync as rmSync12, statSync as statSync24 } from "node:fs";
73615
+ import { cpSync as cpSync2, existsSync as existsSync55, mkdirSync as mkdirSync30, readFileSync as readFileSync49, realpathSync as realpathSync5, rmSync as rmSync12, statSync as statSync24 } from "node:fs";
73488
73616
  import { spawnSync as spawnSync8 } from "node:child_process";
73489
73617
  import { join as join55, dirname as dirname13, resolve as resolve33 } from "node:path";
73490
73618
  import { homedir as homedir33 } from "node:os";
@@ -73494,7 +73622,7 @@ function runningFromSwitchroomCheckout(scriptPath) {
73494
73622
  for (let i = 0;i < 12; i++) {
73495
73623
  if (existsSync55(join55(dir, ".git"))) {
73496
73624
  try {
73497
- const pkg = JSON.parse(readFileSync48(join55(dir, "package.json"), "utf-8"));
73625
+ const pkg = JSON.parse(readFileSync49(join55(dir, "package.json"), "utf-8"));
73498
73626
  if (pkg.name === "switchroom")
73499
73627
  return true;
73500
73628
  } catch {}
@@ -73762,7 +73890,7 @@ function defaultStatusProbe(composePath) {
73762
73890
  const pkgPath = join55(dir, "package.json");
73763
73891
  if (existsSync55(pkgPath)) {
73764
73892
  try {
73765
- const pkg = JSON.parse(readFileSync48(pkgPath, "utf-8"));
73893
+ const pkg = JSON.parse(readFileSync49(pkgPath, "utf-8"));
73766
73894
  if (typeof pkg.version === "string")
73767
73895
  cliVersion = pkg.version;
73768
73896
  } catch (err) {
@@ -73978,7 +74106,7 @@ init_source();
73978
74106
  init_helpers();
73979
74107
  init_lifecycle();
73980
74108
  import { execSync as execSync4 } from "node:child_process";
73981
- import { existsSync as existsSync56, readFileSync as readFileSync49 } from "node:fs";
74109
+ import { existsSync as existsSync56, readFileSync as readFileSync50 } from "node:fs";
73982
74110
  import { dirname as dirname14, join as join56 } from "node:path";
73983
74111
  function getClaudeCodeVersion() {
73984
74112
  try {
@@ -74032,7 +74160,7 @@ function locateSwitchroomInstallDir() {
74032
74160
  const pkgPath = join56(dir, "package.json");
74033
74161
  if (existsSync56(pkgPath)) {
74034
74162
  try {
74035
- const pkg = JSON.parse(readFileSync49(pkgPath, "utf-8"));
74163
+ const pkg = JSON.parse(readFileSync50(pkgPath, "utf-8"));
74036
74164
  if (pkg.name === "switchroom" && existsSync56(join56(dir, ".git"))) {
74037
74165
  return dir;
74038
74166
  }
@@ -74263,7 +74391,7 @@ import {
74263
74391
  mkdirSync as mkdirSync31,
74264
74392
  openSync as openSync11,
74265
74393
  readdirSync as readdirSync21,
74266
- readFileSync as readFileSync50,
74394
+ readFileSync as readFileSync51,
74267
74395
  renameSync as renameSync12,
74268
74396
  statSync as statSync25,
74269
74397
  unlinkSync as unlinkSync11,
@@ -74673,7 +74801,7 @@ function readAll(stateDir) {
74673
74801
  return [];
74674
74802
  let raw;
74675
74803
  try {
74676
- raw = readFileSync50(path4, "utf-8");
74804
+ raw = readFileSync51(path4, "utf-8");
74677
74805
  } catch {
74678
74806
  return [];
74679
74807
  }
@@ -74884,7 +75012,7 @@ function withLock(stateDir, fn) {
74884
75012
  function tryStealStaleLock(lockPath) {
74885
75013
  let pidStr;
74886
75014
  try {
74887
- pidStr = readFileSync50(lockPath, "utf-8").trim();
75015
+ pidStr = readFileSync51(lockPath, "utf-8").trim();
74888
75016
  } catch {
74889
75017
  return true;
74890
75018
  }
@@ -75141,13 +75269,13 @@ import { createHash as createHash11 } from "node:crypto";
75141
75269
  import {
75142
75270
  existsSync as existsSync58,
75143
75271
  mkdirSync as mkdirSync32,
75144
- readFileSync as readFileSync51,
75272
+ readFileSync as readFileSync52,
75145
75273
  rmSync as rmSync13,
75146
75274
  writeFileSync as writeFileSync27
75147
75275
  } from "node:fs";
75148
75276
  import { dirname as dirname15, join as join58 } from "node:path";
75149
75277
  import { homedir as homedir34 } from "node:os";
75150
- import { execFileSync as execFileSync17 } from "node:child_process";
75278
+ import { execFileSync as execFileSync18 } from "node:child_process";
75151
75279
 
75152
75280
  class PythonEnvError extends Error {
75153
75281
  stderr;
@@ -75161,7 +75289,7 @@ function defaultPythonCacheRoot() {
75161
75289
  return join58(homedir34(), ".switchroom", "deps", "python");
75162
75290
  }
75163
75291
  function hashFile(path4) {
75164
- return createHash11("sha256").update(readFileSync51(path4)).digest("hex");
75292
+ return createHash11("sha256").update(readFileSync52(path4)).digest("hex");
75165
75293
  }
75166
75294
  function ensurePythonEnv(opts) {
75167
75295
  const { skillName, requirementsPath, force = false } = opts;
@@ -75177,7 +75305,7 @@ function ensurePythonEnv(opts) {
75177
75305
  const pipBin = join58(binDir, "pip");
75178
75306
  const targetHash = hashFile(requirementsPath);
75179
75307
  if (!force && existsSync58(stampPath) && existsSync58(pythonBin)) {
75180
- const existingHash = readFileSync51(stampPath, "utf8").trim();
75308
+ const existingHash = readFileSync52(stampPath, "utf8").trim();
75181
75309
  if (existingHash === targetHash) {
75182
75310
  return {
75183
75311
  skillName,
@@ -75194,7 +75322,7 @@ function ensurePythonEnv(opts) {
75194
75322
  }
75195
75323
  mkdirSync32(dirname15(venvDir), { recursive: true });
75196
75324
  try {
75197
- execFileSync17(hostPython, ["-m", "venv", venvDir], { stdio: "pipe" });
75325
+ execFileSync18(hostPython, ["-m", "venv", venvDir], { stdio: "pipe" });
75198
75326
  } catch (err) {
75199
75327
  const e = err;
75200
75328
  throw new PythonEnvError(`Failed to create venv for skill "${skillName}" with ${hostPython}: ${e.message}`, e.stderr?.toString());
@@ -75206,7 +75334,7 @@ function ensurePythonEnv(opts) {
75206
75334
  delete childEnv.PIP_TARGET;
75207
75335
  delete childEnv.PIP_PREFIX;
75208
75336
  delete childEnv.PYTHONUSERBASE;
75209
- execFileSync17(pipBin, ["install", "--disable-pip-version-check", "-r", requirementsPath], { stdio: "pipe", env: childEnv });
75337
+ execFileSync18(pipBin, ["install", "--disable-pip-version-check", "-r", requirementsPath], { stdio: "pipe", env: childEnv });
75210
75338
  } catch (err) {
75211
75339
  const e = err;
75212
75340
  throw new PythonEnvError(`Failed to install requirements for skill "${skillName}": ${e.message}`, e.stderr?.toString());
@@ -75229,13 +75357,13 @@ import {
75229
75357
  copyFileSync as copyFileSync9,
75230
75358
  existsSync as existsSync59,
75231
75359
  mkdirSync as mkdirSync33,
75232
- readFileSync as readFileSync52,
75360
+ readFileSync as readFileSync53,
75233
75361
  rmSync as rmSync14,
75234
75362
  writeFileSync as writeFileSync28
75235
75363
  } from "node:fs";
75236
75364
  import { dirname as dirname16, join as join59 } from "node:path";
75237
75365
  import { homedir as homedir35 } from "node:os";
75238
- import { execFileSync as execFileSync18 } from "node:child_process";
75366
+ import { execFileSync as execFileSync19 } from "node:child_process";
75239
75367
 
75240
75368
  class NodeEnvError extends Error {
75241
75369
  stderr;
@@ -75264,7 +75392,7 @@ function hashDepInputs(packageJsonPath) {
75264
75392
  const hasher = createHash12("sha256");
75265
75393
  hasher.update(`package.json
75266
75394
  `);
75267
- hasher.update(readFileSync52(packageJsonPath));
75395
+ hasher.update(readFileSync53(packageJsonPath));
75268
75396
  for (const lockName of ALL_LOCKFILES) {
75269
75397
  const lockPath = join59(sourceDir, lockName);
75270
75398
  if (existsSync59(lockPath)) {
@@ -75273,7 +75401,7 @@ function hashDepInputs(packageJsonPath) {
75273
75401
  hasher.update(lockName);
75274
75402
  hasher.update(`
75275
75403
  `);
75276
- hasher.update(readFileSync52(lockPath));
75404
+ hasher.update(readFileSync53(lockPath));
75277
75405
  }
75278
75406
  }
75279
75407
  return hasher.digest("hex");
@@ -75292,7 +75420,7 @@ function ensureNodeEnv(opts) {
75292
75420
  const binDir = join59(nodeModulesDir, ".bin");
75293
75421
  const targetHash = hashDepInputs(packageJsonPath);
75294
75422
  if (!force && existsSync59(stampPath) && existsSync59(nodeModulesDir)) {
75295
- const existingHash = readFileSync52(stampPath, "utf8").trim();
75423
+ const existingHash = readFileSync53(stampPath, "utf8").trim();
75296
75424
  if (existingHash === targetHash) {
75297
75425
  return {
75298
75426
  skillName,
@@ -75319,10 +75447,10 @@ function ensureNodeEnv(opts) {
75319
75447
  try {
75320
75448
  if (installer === "bun") {
75321
75449
  const args = copiedLockfile ? ["install", "--frozen-lockfile"] : ["install"];
75322
- execFileSync18("bun", args, { cwd: envDir, stdio: "pipe" });
75450
+ execFileSync19("bun", args, { cwd: envDir, stdio: "pipe" });
75323
75451
  } else {
75324
75452
  const args = copiedLockfile ? ["ci"] : ["install"];
75325
- execFileSync18("npm", args, { cwd: envDir, stdio: "pipe" });
75453
+ execFileSync19("npm", args, { cwd: envDir, stdio: "pipe" });
75326
75454
  }
75327
75455
  } catch (err) {
75328
75456
  const e = err;
@@ -76311,7 +76439,7 @@ function safeParseInt(value, fallback) {
76311
76439
  init_helpers();
76312
76440
  init_loader();
76313
76441
  init_merge();
76314
- import { copyFileSync as copyFileSync10, existsSync as existsSync62, readFileSync as readFileSync53, writeFileSync as writeFileSync29 } from "node:fs";
76442
+ import { copyFileSync as copyFileSync10, existsSync as existsSync62, readFileSync as readFileSync54, writeFileSync as writeFileSync29 } from "node:fs";
76315
76443
  import { join as join61, resolve as resolve39 } from "node:path";
76316
76444
  init_schema();
76317
76445
  function resolveSoulTargetOrExit(program3, agentName) {
@@ -76357,7 +76485,7 @@ function registerSoulCommand(program3) {
76357
76485
  console.error(`soul: ${t.soulPath} does not exist yet \u2014 run ` + `\`switchroom soul reset ${agentName}\` to seed it.`);
76358
76486
  process.exit(1);
76359
76487
  }
76360
- process.stdout.write(readFileSync53(t.soulPath, "utf-8"));
76488
+ process.stdout.write(readFileSync54(t.soulPath, "utf-8"));
76361
76489
  }));
76362
76490
  cmd.command("reset <agent>").description("Re-seed SOUL.md from the agent's current profile " + "(backs the existing file up to SOUL.md.bak first)").option("-y, --yes", "Skip the confirmation prompt").action(withConfigError(async (agentName, opts) => {
76363
76491
  const t = resolveSoulTargetOrExit(program3, agentName);
@@ -76402,7 +76530,7 @@ function registerSoulCommand(program3) {
76402
76530
  // src/cli/debug.ts
76403
76531
  init_helpers();
76404
76532
  init_loader();
76405
- import { existsSync as existsSync63, readFileSync as readFileSync54, readdirSync as readdirSync22, statSync as statSync26 } from "node:fs";
76533
+ import { existsSync as existsSync63, readFileSync as readFileSync55, readdirSync as readdirSync22, statSync as statSync26 } from "node:fs";
76406
76534
  import { resolve as resolve40, join as join62 } from "node:path";
76407
76535
  import { createHash as createHash13 } from "node:crypto";
76408
76536
  init_merge();
@@ -76442,7 +76570,7 @@ function findLatestTranscriptJsonl(claudeConfigDir) {
76442
76570
  }
76443
76571
  function extractLatestUserMessage(transcriptPath) {
76444
76572
  try {
76445
- const content = readFileSync54(transcriptPath, "utf-8");
76573
+ const content = readFileSync55(transcriptPath, "utf-8");
76446
76574
  const lines = content.trim().split(`
76447
76575
  `).filter(Boolean);
76448
76576
  for (let i = lines.length - 1;i >= 0; i--) {
@@ -76546,7 +76674,7 @@ function registerDebugCommand(program3) {
76546
76674
  }
76547
76675
  console.log(`=== Append System Prompt (per-session) ===
76548
76676
  `);
76549
- const handoffContent = existsSync63(handoffPath) ? readFileSync54(handoffPath, "utf-8") : "";
76677
+ const handoffContent = existsSync63(handoffPath) ? readFileSync55(handoffPath, "utf-8") : "";
76550
76678
  if (handoffContent.trim().length > 0) {
76551
76679
  console.log(`-- Handoff Briefing (${formatBytes(handoffContent.length)}) --`);
76552
76680
  console.log(handoffContent);
@@ -76557,7 +76685,7 @@ function registerDebugCommand(program3) {
76557
76685
  }
76558
76686
  console.log(`=== CLAUDE.md (auto-loaded by Claude Code) ===
76559
76687
  `);
76560
- const claudeMdContent = existsSync63(claudeMdPath) ? readFileSync54(claudeMdPath, "utf-8") : "";
76688
+ const claudeMdContent = existsSync63(claudeMdPath) ? readFileSync55(claudeMdPath, "utf-8") : "";
76561
76689
  if (claudeMdContent.trim().length > 0) {
76562
76690
  console.log(`(${formatBytes(claudeMdContent.length)})`);
76563
76691
  console.log(claudeMdContent);
@@ -76568,7 +76696,7 @@ function registerDebugCommand(program3) {
76568
76696
  }
76569
76697
  console.log(`=== Persona (SOUL.md) ===
76570
76698
  `);
76571
- const soulMdContent = existsSync63(soulMdPath) ? readFileSync54(soulMdPath, "utf-8") : existsSync63(workspaceSoulMdPath) ? readFileSync54(workspaceSoulMdPath, "utf-8") : "";
76699
+ const soulMdContent = existsSync63(soulMdPath) ? readFileSync55(soulMdPath, "utf-8") : existsSync63(workspaceSoulMdPath) ? readFileSync55(workspaceSoulMdPath, "utf-8") : "";
76572
76700
  if (soulMdContent.trim().length > 0) {
76573
76701
  console.log(`(${formatBytes(soulMdContent.length)})`);
76574
76702
  console.log(soulMdContent);
@@ -76648,7 +76776,7 @@ function registerDebugCommand(program3) {
76648
76776
  init_source();
76649
76777
 
76650
76778
  // src/worktree/claim.ts
76651
- import { execFileSync as execFileSync19 } from "node:child_process";
76779
+ import { execFileSync as execFileSync20 } from "node:child_process";
76652
76780
  import { closeSync as closeSync12, mkdirSync as mkdirSync35, openSync as openSync12, existsSync as existsSync65, unlinkSync as unlinkSync13 } from "node:fs";
76653
76781
  import { join as join64, resolve as resolve42 } from "node:path";
76654
76782
  import { homedir as homedir38 } from "node:os";
@@ -76658,7 +76786,7 @@ import { randomBytes as randomBytes13 } from "node:crypto";
76658
76786
  import {
76659
76787
  mkdirSync as mkdirSync34,
76660
76788
  writeFileSync as writeFileSync30,
76661
- readFileSync as readFileSync55,
76789
+ readFileSync as readFileSync56,
76662
76790
  readdirSync as readdirSync23,
76663
76791
  unlinkSync as unlinkSync12,
76664
76792
  existsSync as existsSync64,
@@ -76686,7 +76814,7 @@ function writeRecord(record2) {
76686
76814
  function readRecord(id) {
76687
76815
  const path7 = recordPath(id);
76688
76816
  try {
76689
- const raw = readFileSync55(path7, "utf8");
76817
+ const raw = readFileSync56(path7, "utf8");
76690
76818
  return JSON.parse(raw);
76691
76819
  } catch {
76692
76820
  return null;
@@ -76815,7 +76943,7 @@ async function claimWorktree(input, codeRepos) {
76815
76943
  releaseLock();
76816
76944
  }
76817
76945
  try {
76818
- execFileSync19("git", ["worktree", "add", "-b", branch, worktreePath], {
76946
+ execFileSync20("git", ["worktree", "add", "-b", branch, worktreePath], {
76819
76947
  cwd: repoPath,
76820
76948
  stdio: "pipe"
76821
76949
  });
@@ -76828,7 +76956,7 @@ async function claimWorktree(input, codeRepos) {
76828
76956
  }
76829
76957
 
76830
76958
  // src/worktree/release.ts
76831
- import { execFileSync as execFileSync20 } from "node:child_process";
76959
+ import { execFileSync as execFileSync21 } from "node:child_process";
76832
76960
  import { existsSync as existsSync66 } from "node:fs";
76833
76961
  function releaseWorktree(input) {
76834
76962
  const { id } = input;
@@ -76839,7 +76967,7 @@ function releaseWorktree(input) {
76839
76967
  let gitSuccess = true;
76840
76968
  if (existsSync66(record2.path)) {
76841
76969
  try {
76842
- execFileSync20("git", ["worktree", "remove", "--force", record2.path], {
76970
+ execFileSync21("git", ["worktree", "remove", "--force", record2.path], {
76843
76971
  cwd: record2.repo,
76844
76972
  stdio: "pipe"
76845
76973
  });
@@ -76875,16 +77003,16 @@ function listWorktrees() {
76875
77003
  }
76876
77004
 
76877
77005
  // src/worktree/reaper.ts
76878
- import { execFileSync as execFileSync21 } from "node:child_process";
77006
+ import { execFileSync as execFileSync22 } from "node:child_process";
76879
77007
  import { existsSync as existsSync67 } from "node:fs";
76880
77008
  var STALE_THRESHOLD_MS = 10 * 60 * 1000;
76881
77009
  function isPathInUse(path7) {
76882
77010
  try {
76883
- execFileSync21("fuser", [path7], { stdio: "pipe" });
77011
+ execFileSync22("fuser", [path7], { stdio: "pipe" });
76884
77012
  return true;
76885
77013
  } catch {}
76886
77014
  try {
76887
- const out = execFileSync21("lsof", ["-t", path7], {
77015
+ const out = execFileSync22("lsof", ["-t", path7], {
76888
77016
  stdio: ["ignore", "pipe", "ignore"]
76889
77017
  }).toString().trim();
76890
77018
  if (out.length > 0)
@@ -76894,7 +77022,7 @@ function isPathInUse(path7) {
76894
77022
  }
76895
77023
  function hasUncommittedChanges(repoPath, worktreePath) {
76896
77024
  try {
76897
- const out = execFileSync21("git", ["-C", worktreePath, "status", "--porcelain"], { stdio: "pipe" }).toString();
77025
+ const out = execFileSync22("git", ["-C", worktreePath, "status", "--porcelain"], { stdio: "pipe" }).toString();
76898
77026
  return out.trim().length > 0;
76899
77027
  } catch {
76900
77028
  return false;
@@ -76908,7 +77036,7 @@ function reapRecord(record2) {
76908
77036
  warning = `[worktree-reaper] Reaped worktree with uncommitted changes: ` + `id=${id} branch=${branch} agent=${ownerAgent ?? "unknown"} path=${path7}`;
76909
77037
  }
76910
77038
  try {
76911
- execFileSync21("git", ["worktree", "remove", "--force", path7], {
77039
+ execFileSync22("git", ["worktree", "remove", "--force", path7], {
76912
77040
  cwd: repo,
76913
77041
  stdio: "pipe"
76914
77042
  });
@@ -78000,7 +78128,7 @@ async function fetchToken(vaultKey) {
78000
78128
 
78001
78129
  // src/cli/apply.ts
78002
78130
  init_source();
78003
- import { accessSync as accessSync3, chownSync as chownSync4, constants as fsConstants6, copyFileSync as copyFileSync11, existsSync as existsSync72, mkdirSync as mkdirSync40, readFileSync as readFileSync57, readdirSync as readdirSync26, renameSync as renameSync14, writeFileSync as writeFileSync35 } from "node:fs";
78131
+ import { accessSync as accessSync3, chownSync as chownSync4, constants as fsConstants6, copyFileSync as copyFileSync11, existsSync as existsSync72, mkdirSync as mkdirSync40, readFileSync as readFileSync58, readdirSync as readdirSync26, renameSync as renameSync14, writeFileSync as writeFileSync35 } from "node:fs";
78004
78132
  import { mkdir, writeFile } from "node:fs/promises";
78005
78133
  import { spawnSync as childSpawnSync } from "node:child_process";
78006
78134
  import readline from "node:readline";
@@ -78391,13 +78519,13 @@ agents:
78391
78519
  init_resolver();
78392
78520
  import { dirname as dirname21, join as join70, resolve as resolve44 } from "node:path";
78393
78521
  import { homedir as homedir40 } from "node:os";
78394
- import { execFileSync as execFileSync22 } from "node:child_process";
78522
+ import { execFileSync as execFileSync23 } from "node:child_process";
78395
78523
  init_vault();
78396
78524
  init_loader();
78397
78525
  init_loader();
78398
78526
 
78399
78527
  // src/cli/update-prompt-hook.ts
78400
- import { existsSync as existsSync69, readFileSync as readFileSync56, writeFileSync as writeFileSync34, chmodSync as chmodSync10, mkdirSync as mkdirSync39 } from "node:fs";
78528
+ import { existsSync as existsSync69, readFileSync as readFileSync57, writeFileSync as writeFileSync34, chmodSync as chmodSync10, mkdirSync as mkdirSync39 } from "node:fs";
78401
78529
  import { join as join67 } from "node:path";
78402
78530
  var HOOK_FILENAME = "update-card-on-prompt.sh";
78403
78531
  function updatePromptHookScript() {
@@ -78469,7 +78597,7 @@ function installUpdatePromptHook(agentDir) {
78469
78597
  const scriptPath = join67(hooksDir, HOOK_FILENAME);
78470
78598
  const desired = updatePromptHookScript();
78471
78599
  let installed = false;
78472
- const existing = existsSync69(scriptPath) ? readFileSync56(scriptPath, "utf-8") : "";
78600
+ const existing = existsSync69(scriptPath) ? readFileSync57(scriptPath, "utf-8") : "";
78473
78601
  if (existing !== desired) {
78474
78602
  writeFileSync34(scriptPath, desired, { mode: 493 });
78475
78603
  chmodSync10(scriptPath, 493);
@@ -78483,7 +78611,7 @@ function installUpdatePromptHook(agentDir) {
78483
78611
  if (!existsSync69(settingsPath)) {
78484
78612
  return { scriptPath, settingsPath, installed };
78485
78613
  }
78486
- const raw = readFileSync56(settingsPath, "utf-8");
78614
+ const raw = readFileSync57(settingsPath, "utf-8");
78487
78615
  let parsed;
78488
78616
  try {
78489
78617
  parsed = JSON.parse(raw);
@@ -78777,7 +78905,7 @@ async function ensureHostMountSources(config) {
78777
78905
  await mkdir(fleetDir, { recursive: true });
78778
78906
  const invariantsPath = join70(fleetDir, "switchroom-invariants.md");
78779
78907
  const invariantsCanonical = renderFleetInvariants();
78780
- const invariantsCurrent = existsSync72(invariantsPath) ? readFileSync57(invariantsPath, "utf-8") : null;
78908
+ const invariantsCurrent = existsSync72(invariantsPath) ? readFileSync58(invariantsPath, "utf-8") : null;
78781
78909
  if (invariantsCurrent !== invariantsCanonical) {
78782
78910
  writeFileSync35(invariantsPath, invariantsCanonical, { mode: 420 });
78783
78911
  }
@@ -78799,7 +78927,7 @@ async function ensureHostMountSources(config) {
78799
78927
  }
78800
78928
  function detectComposeV2() {
78801
78929
  try {
78802
- const out = execFileSync22("docker", ["compose", "version"], {
78930
+ const out = execFileSync23("docker", ["compose", "version"], {
78803
78931
  stdio: ["ignore", "pipe", "pipe"],
78804
78932
  encoding: "utf8"
78805
78933
  });
@@ -79314,7 +79442,7 @@ function runRedactStdin() {
79314
79442
  }
79315
79443
 
79316
79444
  // src/cli/status-ask.ts
79317
- import { readFileSync as readFileSync58, existsSync as existsSync73, readdirSync as readdirSync27 } from "node:fs";
79445
+ import { readFileSync as readFileSync59, existsSync as existsSync73, readdirSync as readdirSync27 } from "node:fs";
79318
79446
  import { join as join71 } from "node:path";
79319
79447
  import { homedir as homedir41 } from "node:os";
79320
79448
 
@@ -79590,7 +79718,7 @@ function runReport(opts) {
79590
79718
  for (const src of sources) {
79591
79719
  let content;
79592
79720
  try {
79593
- content = readFileSync58(src.path, "utf-8");
79721
+ content = readFileSync59(src.path, "utf-8");
79594
79722
  } catch (err) {
79595
79723
  process.stderr.write(`status-ask report: cannot read ${src.path}: ${err instanceof Error ? err.message : String(err)}
79596
79724
  `);
@@ -79691,7 +79819,7 @@ import {
79691
79819
  existsSync as existsSync74,
79692
79820
  mkdirSync as mkdirSync41,
79693
79821
  appendFileSync as appendFileSync4,
79694
- readFileSync as readFileSync59
79822
+ readFileSync as readFileSync60
79695
79823
  } from "node:fs";
79696
79824
  var AUDIT_ROOT = join72(homedir42(), ".switchroom", "audit");
79697
79825
  function auditPathFor(agent) {
@@ -79786,7 +79914,7 @@ function readAuditTail(agent, limit, opts = {}) {
79786
79914
  return [];
79787
79915
  let raw;
79788
79916
  try {
79789
- raw = readFileSync59(path8, "utf-8");
79917
+ raw = readFileSync60(path8, "utf-8");
79790
79918
  } catch {
79791
79919
  return [];
79792
79920
  }
@@ -79936,7 +80064,7 @@ function registerAgentConfigCommands(program3) {
79936
80064
  }
79937
80065
 
79938
80066
  // src/cli/agent-config-write.ts
79939
- var import_yaml16 = __toESM(require_dist(), 1);
80067
+ var import_yaml17 = __toESM(require_dist(), 1);
79940
80068
 
79941
80069
  // src/config/overlay-writer.ts
79942
80070
  init_paths();
@@ -79947,7 +80075,7 @@ import {
79947
80075
  mkdirSync as mkdirSync42,
79948
80076
  openSync as openSync13,
79949
80077
  readdirSync as readdirSync28,
79950
- readFileSync as readFileSync60,
80078
+ readFileSync as readFileSync61,
79951
80079
  renameSync as renameSync15,
79952
80080
  statSync as statSync28,
79953
80081
  unlinkSync as unlinkSync14,
@@ -80071,7 +80199,7 @@ function listSkillsOverlayEntries(agent, opts = {}) {
80071
80199
  continue;
80072
80200
  const full = join73(paths.skillsDir, name);
80073
80201
  try {
80074
- const raw = readFileSync60(full, "utf-8");
80202
+ const raw = readFileSync61(full, "utf-8");
80075
80203
  const slug = name.replace(/\.ya?ml$/i, "");
80076
80204
  out.push({ slug, path: full, raw });
80077
80205
  } catch {}
@@ -80098,7 +80226,7 @@ function listOverlayEntries(agent, opts = {}) {
80098
80226
  continue;
80099
80227
  const full = join73(paths.scheduleDir, name);
80100
80228
  try {
80101
- const raw = readFileSync60(full, "utf-8");
80229
+ const raw = readFileSync61(full, "utf-8");
80102
80230
  const slug = name.replace(/\.ya?ml$/i, "");
80103
80231
  out.push({ slug, path: full, raw });
80104
80232
  } catch {}
@@ -80129,7 +80257,7 @@ function filterOverlaySecrets(doc, source) {
80129
80257
  // src/agents/reconcile-dry-run.ts
80130
80258
  init_overlay_schema();
80131
80259
  init_schema();
80132
- var import_yaml15 = __toESM(require_dist(), 1);
80260
+ var import_yaml16 = __toESM(require_dist(), 1);
80133
80261
  init_lifecycle();
80134
80262
  var MIN_CRON_INTERVAL_SECS = 5 * 60;
80135
80263
  function violatesMinInterval(cron) {
@@ -80151,7 +80279,7 @@ function violatesMinInterval(cron) {
80151
80279
  function dryRunReconcile(input) {
80152
80280
  let parsed;
80153
80281
  try {
80154
- parsed = import_yaml15.parse(input.yamlText);
80282
+ parsed = import_yaml16.parse(input.yamlText);
80155
80283
  } catch (err) {
80156
80284
  return {
80157
80285
  ok: false,
@@ -80246,7 +80374,7 @@ import {
80246
80374
  mkdirSync as mkdirSync43,
80247
80375
  openSync as openSync14,
80248
80376
  readdirSync as readdirSync29,
80249
- readFileSync as readFileSync61,
80377
+ readFileSync as readFileSync62,
80250
80378
  renameSync as renameSync16,
80251
80379
  unlinkSync as unlinkSync15,
80252
80380
  writeFileSync as writeFileSync36,
@@ -80310,7 +80438,7 @@ function listPendingScheduleEntries(agent, opts = {}) {
80310
80438
  if (!existsSync76(yamlPath))
80311
80439
  continue;
80312
80440
  try {
80313
- const meta = JSON.parse(readFileSync61(metaPath, "utf-8"));
80441
+ const meta = JSON.parse(readFileSync62(metaPath, "utf-8"));
80314
80442
  if (meta?.v !== 1 || typeof meta.stage_id !== "string")
80315
80443
  continue;
80316
80444
  out.push({ stageId: meta.stage_id, agent: meta.agent, yamlPath, metaPath, meta });
@@ -80349,7 +80477,7 @@ function denyPendingScheduleEntry(opts) {
80349
80477
 
80350
80478
  // src/cli/agent-config-write.ts
80351
80479
  init_protocol3();
80352
- import { existsSync as existsSync77, readFileSync as readFileSync62 } from "node:fs";
80480
+ import { existsSync as existsSync77, readFileSync as readFileSync63 } from "node:fs";
80353
80481
  var MAX_ENTRIES_PER_AGENT = 20;
80354
80482
  var MIN_CRON_INTERVAL_MIN = 5;
80355
80483
  function extractCronSmallestGapMin(expr) {
@@ -80457,7 +80585,7 @@ function scheduleAdd(opts) {
80457
80585
  ]
80458
80586
  };
80459
80587
  const yamlText = (() => {
80460
- const body = import_yaml16.stringify(doc);
80588
+ const body = import_yaml17.stringify(doc);
80461
80589
  const header = opts.name ? `# name: ${opts.name}
80462
80590
  ` : "";
80463
80591
  return header + body;
@@ -80567,7 +80695,7 @@ function scheduleAddOrStage(opts) {
80567
80695
  ]
80568
80696
  };
80569
80697
  const yamlText = (opts.name ? `# name: ${opts.name}
80570
- ` : "") + import_yaml16.stringify(doc);
80698
+ ` : "") + import_yaml17.stringify(doc);
80571
80699
  const summary = (() => {
80572
80700
  const parts = [`cron=${opts.cronExpr}`];
80573
80701
  if (opts.secrets?.length)
@@ -80617,7 +80745,7 @@ function scheduleRemove(opts) {
80617
80745
  break;
80618
80746
  }
80619
80747
  try {
80620
- const parsed = import_yaml16.parse(e.raw);
80748
+ const parsed = import_yaml17.parse(e.raw);
80621
80749
  if (parsed && parsed.name === opts.name) {
80622
80750
  match = e;
80623
80751
  break;
@@ -80636,7 +80764,7 @@ function scheduleRemove(opts) {
80636
80764
  let priorContent = null;
80637
80765
  try {
80638
80766
  if (existsSync77(match.path))
80639
- priorContent = readFileSync62(match.path, "utf-8");
80767
+ priorContent = readFileSync63(match.path, "utf-8");
80640
80768
  } catch {}
80641
80769
  deleteOverlayEntry(agent, match.slug, { root: opts.root });
80642
80770
  const reconcileFn = opts.reconcile === undefined ? opts.root ? null : reconcileAgentCronOnly : opts.reconcile;
@@ -80827,10 +80955,10 @@ function registerAgentConfigWriteCommands(program3) {
80827
80955
  }
80828
80956
 
80829
80957
  // src/cli/agent-config-skill-write.ts
80830
- var import_yaml17 = __toESM(require_dist(), 1);
80958
+ var import_yaml18 = __toESM(require_dist(), 1);
80831
80959
  import { existsSync as existsSync78 } from "node:fs";
80832
80960
  init_reconcile_default_skills();
80833
- var import_yaml18 = __toESM(require_dist(), 1);
80961
+ var import_yaml19 = __toESM(require_dist(), 1);
80834
80962
  import { join as join75 } from "node:path";
80835
80963
  var MAX_SKILLS_PER_AGENT = 20;
80836
80964
  var V1_ALLOWED_SOURCE_PREFIX = "bundled:";
@@ -80880,7 +81008,7 @@ function countCurrentSkills(agent, opts) {
80880
81008
  let total = 0;
80881
81009
  for (const e of entries) {
80882
81010
  try {
80883
- const doc = import_yaml18.parse(e.raw);
81011
+ const doc = import_yaml19.parse(e.raw);
80884
81012
  total += (doc?.skills ?? []).length;
80885
81013
  } catch {}
80886
81014
  }
@@ -80910,7 +81038,7 @@ function skillInstall(opts) {
80910
81038
  if (!existsSync78(skillPath)) {
80911
81039
  return err("E_SKILL_NOT_FOUND", `bundled skill not found at ${skillPath}. The operator needs to ` + `place the skill at this path before the agent can opt in.`);
80912
81040
  }
80913
- const yamlText = import_yaml17.stringify({ skills: [skillName] });
81041
+ const yamlText = import_yaml18.stringify({ skills: [skillName] });
80914
81042
  let path8;
80915
81043
  try {
80916
81044
  path8 = writeSkillsOverlayEntry(agent, slug, yamlText, { root: opts.root });
@@ -81076,7 +81204,7 @@ import {
81076
81204
  mkdirSync as mkdirSync44,
81077
81205
  mkdtempSync as mkdtempSync5,
81078
81206
  openSync as openSync15,
81079
- readFileSync as readFileSync63,
81207
+ readFileSync as readFileSync64,
81080
81208
  readdirSync as readdirSync30,
81081
81209
  realpathSync as realpathSync7,
81082
81210
  renameSync as renameSync17,
@@ -81089,7 +81217,7 @@ import { dirname as dirname22, join as join76, relative as relative2, resolve as
81089
81217
  import { spawnSync as spawnSync10 } from "node:child_process";
81090
81218
 
81091
81219
  // src/cli/skill-common.ts
81092
- var import_yaml19 = __toESM(require_dist(), 1);
81220
+ var import_yaml20 = __toESM(require_dist(), 1);
81093
81221
  var MAX_FILE_BYTES = 256 * 1024;
81094
81222
  var MAX_SKILL_BYTES = 2 * 1024 * 1024;
81095
81223
  var MAX_FILES_PER_SKILL = 50;
@@ -81193,7 +81321,7 @@ function validateSkillMd(content, expectedName) {
81193
81321
  }
81194
81322
  let parsed;
81195
81323
  try {
81196
- parsed = import_yaml19.parse(fmText);
81324
+ parsed = import_yaml20.parse(fmText);
81197
81325
  } catch (e) {
81198
81326
  return authorErr("E_SKILL_INVALID_FRONTMATTER", `frontmatter is not valid YAML: ${e.message}`);
81199
81327
  }
@@ -81328,7 +81456,7 @@ function loadFromDir(dir) {
81328
81456
  continue;
81329
81457
  }
81330
81458
  if (ent.isFile()) {
81331
- const buf = readFileSync63(full);
81459
+ const buf = readFileSync64(full);
81332
81460
  files[rel.replace(/\\/g, "/")] = buf.toString("utf-8");
81333
81461
  }
81334
81462
  }
@@ -81377,7 +81505,7 @@ function loadFromTarball(tarPath) {
81377
81505
  }
81378
81506
  }
81379
81507
  function loadSingleFile(filePath) {
81380
- const content = readFileSync63(filePath, "utf-8");
81508
+ const content = readFileSync64(filePath, "utf-8");
81381
81509
  return { "SKILL.md": content };
81382
81510
  }
81383
81511
  function loadFromStdin() {
@@ -81468,7 +81596,7 @@ function diffSummary(currentDir, files) {
81468
81596
  if (ent.isDirectory()) {
81469
81597
  walk2(full);
81470
81598
  } else if (ent.isFile()) {
81471
- currentFiles[rel.replace(/\\/g, "/")] = readFileSync63(full, "utf-8");
81599
+ currentFiles[rel.replace(/\\/g, "/")] = readFileSync64(full, "utf-8");
81472
81600
  }
81473
81601
  }
81474
81602
  };
@@ -81628,7 +81756,7 @@ import {
81628
81756
  mkdirSync as mkdirSync45,
81629
81757
  mkdtempSync as mkdtempSync6,
81630
81758
  openSync as openSync16,
81631
- readFileSync as readFileSync64,
81759
+ readFileSync as readFileSync65,
81632
81760
  readdirSync as readdirSync31,
81633
81761
  renameSync as renameSync18,
81634
81762
  rmSync as rmSync17,
@@ -81710,7 +81838,7 @@ function mirrorToConfigRepo(agent, name, liveSkillDir) {
81710
81838
  if (ent.isDirectory())
81711
81839
  walk2(s, d);
81712
81840
  else if (ent.isFile()) {
81713
- writeFileSync38(d, readFileSync64(s));
81841
+ writeFileSync38(d, readFileSync65(s));
81714
81842
  }
81715
81843
  }
81716
81844
  };
@@ -81789,7 +81917,7 @@ function loadFromDir2(dir) {
81789
81917
  }
81790
81918
  if (ent.isFile()) {
81791
81919
  const rel = relative3(abs, full).replace(/\\/g, "/");
81792
- files[rel] = readFileSync64(full, "utf-8");
81920
+ files[rel] = readFileSync65(full, "utf-8");
81793
81921
  }
81794
81922
  }
81795
81923
  };
@@ -81975,7 +82103,7 @@ function loadFiles(opts) {
81975
82103
  return loadFromDir2(p);
81976
82104
  }
81977
82105
  if (p.endsWith(".md")) {
81978
- return { "SKILL.md": readFileSync64(p, "utf-8") };
82106
+ return { "SKILL.md": readFileSync65(p, "utf-8") };
81979
82107
  }
81980
82108
  fail3(`--from must be a directory or a .md file. Got: ${opts.from}`);
81981
82109
  }
@@ -82064,7 +82192,7 @@ function readSourceFiles(dir) {
82064
82192
  fail3(`clone source has oversized file ${rel} (${st.size} bytes > ${CLONE_MAX_FILE_BYTES}); ` + `refuse to read`, 3);
82065
82193
  }
82066
82194
  } catch {}
82067
- files[rel] = readFileSync64(full, "utf-8");
82195
+ files[rel] = readFileSync65(full, "utf-8");
82068
82196
  }
82069
82197
  }
82070
82198
  };
@@ -82232,8 +82360,8 @@ function registerSkillPersonalCommands(program3) {
82232
82360
 
82233
82361
  // src/cli/skill-search.ts
82234
82362
  init_helpers();
82235
- var import_yaml20 = __toESM(require_dist(), 1);
82236
- import { existsSync as existsSync81, readdirSync as readdirSync32, readFileSync as readFileSync65, statSync as statSync31 } from "node:fs";
82363
+ var import_yaml21 = __toESM(require_dist(), 1);
82364
+ import { existsSync as existsSync81, readdirSync as readdirSync32, readFileSync as readFileSync66, statSync as statSync31 } from "node:fs";
82237
82365
  import { homedir as homedir45 } from "node:os";
82238
82366
  import { join as join78, resolve as resolve48 } from "node:path";
82239
82367
  var PERSONAL_PREFIX2 = "personal-";
@@ -82254,7 +82382,7 @@ function readSkillFrontmatter(skillDir) {
82254
82382
  return null;
82255
82383
  let content;
82256
82384
  try {
82257
- content = readFileSync65(mdPath, "utf-8");
82385
+ content = readFileSync66(mdPath, "utf-8");
82258
82386
  } catch {
82259
82387
  return null;
82260
82388
  }
@@ -82272,7 +82400,7 @@ function readSkillFrontmatter(skillDir) {
82272
82400
  const fmText = rest.slice(0, endIdx);
82273
82401
  let parsed;
82274
82402
  try {
82275
- parsed = import_yaml20.parse(fmText);
82403
+ parsed = import_yaml21.parse(fmText);
82276
82404
  } catch (e) {
82277
82405
  return { error: `yaml parse: ${e.message}` };
82278
82406
  }
@@ -82526,7 +82654,7 @@ function registerHostdMcpCommand(program3) {
82526
82654
  // src/cli/hostd.ts
82527
82655
  init_source();
82528
82656
  init_helpers();
82529
- import { existsSync as existsSync83, mkdirSync as mkdirSync46, readdirSync as readdirSync33, readFileSync as readFileSync67, writeFileSync as writeFileSync39, statSync as statSync32, copyFileSync as copyFileSync12 } from "node:fs";
82657
+ import { existsSync as existsSync83, mkdirSync as mkdirSync46, readdirSync as readdirSync33, readFileSync as readFileSync68, writeFileSync as writeFileSync39, statSync as statSync32, copyFileSync as copyFileSync12 } from "node:fs";
82530
82658
  import { homedir as homedir46 } from "node:os";
82531
82659
  import { join as join79 } from "node:path";
82532
82660
  import { spawnSync as spawnSync13 } from "node:child_process";
@@ -82781,7 +82909,7 @@ function registerHostdCommand(program3) {
82781
82909
  The log is created when hostd handles its first privileged-verb request.`));
82782
82910
  return;
82783
82911
  }
82784
- const raw = readFileSync67(logPath, "utf-8");
82912
+ const raw = readFileSync68(logPath, "utf-8");
82785
82913
  const limit = Math.max(1, parseInt(opts.tail ?? "50", 10) || 50);
82786
82914
  const filters = {
82787
82915
  agent: opts.agent,