@sideboard-ai/core 0.1.217 → 0.1.218

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.
Files changed (59) hide show
  1. package/dist/{abletime-QGGYL2G4.js → abletime-BF253OZT.js} +5 -4
  2. package/dist/{abletime-GDZLZRMY.js → abletime-D6773P33.js} +5 -5
  3. package/dist/{abletime-oauth-F335TWKY.js → abletime-oauth-H4672PRH.js} +4 -3
  4. package/dist/{abletime-oauth-3X3BAPTF.js → abletime-oauth-KQPVVBKA.js} +4 -4
  5. package/dist/{abletime-rest-PLJVY3H3.js → abletime-rest-DAFPXZ7H.js} +4 -4
  6. package/dist/{abletime-rest-LAGTPAJL.js → abletime-rest-OPEVV3XC.js} +4 -3
  7. package/dist/agents/cursor-runner.js +5 -5
  8. package/dist/{agents-WBDDLRBY.js → agents-NWJ7DFJD.js} +8 -7
  9. package/dist/{agents-HETHRRZJ.js → agents-YABJUV3V.js} +9 -9
  10. package/dist/{app-settings-XCRNCEEE.js → app-settings-5RQMQKSB.js} +2 -1
  11. package/dist/{app-settings-2TN3WLZV.js → app-settings-V2BBCX2H.js} +2 -2
  12. package/dist/{chunk-MN6YUD4O.js → chunk-3NWUHXU3.js} +3 -3
  13. package/dist/{chunk-G4TANQC3.js → chunk-646I442S.js} +5 -5
  14. package/dist/{chunk-FNQNJOHY.js → chunk-ABOBTSO6.js} +4 -1
  15. package/dist/{chunk-YVE4PXCJ.js → chunk-CLI5DVU4.js} +2 -2
  16. package/dist/{chunk-7MTVRNP4.js → chunk-FSIJGLSV.js} +1173 -1186
  17. package/dist/{chunk-LS6TSOCE.js → chunk-HSYE5ID6.js} +5 -5
  18. package/dist/{chunk-UFHNSFAS.js → chunk-HVUVQXZ2.js} +5 -1
  19. package/dist/{chunk-SALM35KD.js → chunk-IILG7DPX.js} +5 -5
  20. package/dist/{chunk-D2IKXMF3.js → chunk-JWBPSD7Q.js} +453 -289
  21. package/dist/{chunk-NI243N27.js → chunk-KTZESHYH.js} +15 -7
  22. package/dist/{chunk-KFD2OXCE.js → chunk-MW57SKKR.js} +19 -6
  23. package/dist/{chunk-XYKVRRC2.js → chunk-NFWPDEN4.js} +15 -7
  24. package/dist/{chunk-FNGXKY5W.js → chunk-OPYBLX4V.js} +19 -6
  25. package/dist/{chunk-QQKDGPUI.js → chunk-PO4M4JAJ.js} +1 -1
  26. package/dist/{chunk-2M5B7YNY.js → chunk-RRW2XWAY.js} +2 -2
  27. package/dist/{chunk-REZRGCKV.js → chunk-SOGGKYFV.js} +3 -3
  28. package/dist/{chunk-C32SBNA3.js → chunk-SRFFIFW6.js} +457 -294
  29. package/dist/{chunk-3OHR73VK.js → chunk-SVXIJ2IC.js} +1 -1
  30. package/dist/{chunk-SYFVUF2C.js → chunk-SZJZEFTY.js} +1 -1
  31. package/dist/{chunk-42IULNIY.js → chunk-THLVCXLF.js} +3 -3
  32. package/dist/{chunk-JZHRZ3DR.js → chunk-TQBUXKIB.js} +5 -5
  33. package/dist/chunk-WWUABK6B.js +56 -0
  34. package/dist/{chunk-DFTVZEZY.js → chunk-XRHTRXZN.js} +1051 -1050
  35. package/dist/{chunk-BTC2D6LS.js → chunk-Y5JES2VV.js} +3 -51
  36. package/dist/{connected-teams-WK47ATT7.js → connected-teams-LX5DLL2I.js} +3 -2
  37. package/dist/{connected-teams-PU4AMFNA.js → connected-teams-PQETXUWV.js} +3 -2
  38. package/dist/{coordinator-prompt-FQX6ALAI.js → coordinator-prompt-5V7GEPBG.js} +6 -6
  39. package/dist/{coordinator-prompt-LE2GQZ2X.js → coordinator-prompt-J4QSNTKE.js} +6 -5
  40. package/dist/{global-workspace-6P236KKG.js → global-workspace-4TEMLESD.js} +6 -6
  41. package/dist/{global-workspace-KT3FRHZL.js → global-workspace-XPTFHMKL.js} +6 -5
  42. package/dist/index.cjs +1027 -821
  43. package/dist/index.d.cts +10 -1
  44. package/dist/index.d.ts +10 -1
  45. package/dist/index.js +22 -18
  46. package/dist/mcp/run-stdio.cjs +1838 -1651
  47. package/dist/mcp/run-stdio.js +16 -14
  48. package/dist/{orchestrator-WVZPTHBV.js → orchestrator-HKW3VLGX.js} +10 -10
  49. package/dist/{orchestrator-MI7A5DQZ.js → orchestrator-SWRTYFHX.js} +9 -8
  50. package/dist/{run-EBWL2Q4N.js → run-QDZCTP4Y.js} +2 -1
  51. package/dist/{run-CAGKZLHA.js → run-UEQM4JMZ.js} +2 -1
  52. package/dist/{workspaces-KM7KTLVO.js → workspaces-2HQP654Q.js} +6 -5
  53. package/dist/{workspaces-R5LJCJRB.js → workspaces-BCBBMMXB.js} +6 -6
  54. package/dist/{worktree-MDMTCAHX.js → worktree-7V67XTEO.js} +5 -5
  55. package/dist/{worktree-VXRI7LYM.js → worktree-I573UOPD.js} +5 -4
  56. package/dist/{worktree-exclude-N5X5I422.js → worktree-exclude-K7QK4RI5.js} +3 -2
  57. package/dist/{worktree-exclude-X54WSOXM.js → worktree-exclude-L32WEBX6.js} +3 -2
  58. package/package.json +1 -1
  59. package/dist/{chunk-L5CIEBLR.js → chunk-EWHJNJHV.js} +3 -3
package/dist/index.cjs CHANGED
@@ -6890,7 +6890,7 @@ async function run(file, args, opts) {
6890
6890
  try {
6891
6891
  const result = await (0, import_execa2.execa)(file, args, {
6892
6892
  cwd: opts?.cwd,
6893
- env: { ...process.env, ...opts?.env },
6893
+ env: { ...stripNestedElectronEnv(process.env), ...opts?.env },
6894
6894
  reject: opts?.reject ?? true,
6895
6895
  ...opts?.timeoutMs != null ? { timeout: opts.timeoutMs } : {}
6896
6896
  });
@@ -6987,6 +6987,7 @@ var init_run = __esm({
6987
6987
  "use strict";
6988
6988
  import_execa2 = require("execa");
6989
6989
  init_path();
6990
+ init_nested_electron_env();
6990
6991
  init_github_agent_auth();
6991
6992
  init_stale_lock();
6992
6993
  }
@@ -8079,7 +8080,14 @@ function slugify(input) {
8079
8080
  }
8080
8081
  async function resolveRepoRoot(cwd) {
8081
8082
  const { stdout } = await git(["rev-parse", "--show-toplevel"], cwd);
8082
- return canonicalizeRepoPath(stdout.trim());
8083
+ const toplevel = canonicalizeRepoPath(stdout.trim());
8084
+ try {
8085
+ const listed = await listWorktrees(cwd);
8086
+ const primary = listed[0]?.path;
8087
+ if (primary) return canonicalizeRepoPath(primary);
8088
+ } catch {
8089
+ }
8090
+ return toplevel;
8083
8091
  }
8084
8092
  function canonicalizeRepoPath(path2) {
8085
8093
  try {
@@ -8099,7 +8107,8 @@ function parseGithubSlugFromRemoteUrl(url) {
8099
8107
  }
8100
8108
  async function slugFromGitRemote(repoPath, remote) {
8101
8109
  const result = await git(["remote", "get-url", remote], repoPath, {
8102
- reject: false
8110
+ reject: false,
8111
+ timeoutMs: 5e3
8103
8112
  });
8104
8113
  if (result.exitCode !== 0 || !result.stdout.trim()) return null;
8105
8114
  return parseGithubSlugFromRemoteUrl(result.stdout);
@@ -8112,7 +8121,7 @@ async function resolveGithubRepoSlug(repoPath) {
8112
8121
  const viaGh = await gh(
8113
8122
  ["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"],
8114
8123
  repoPath,
8115
- { reject: false }
8124
+ { reject: false, timeoutMs: 8e3 }
8116
8125
  );
8117
8126
  if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
8118
8127
  return viaGh.stdout.trim();
@@ -9041,7 +9050,7 @@ async function listWorktrees(repoPath) {
9041
9050
  const { stdout } = await git(
9042
9051
  ["worktree", "list", "--porcelain"],
9043
9052
  repoPath,
9044
- { reject: false }
9053
+ { reject: false, timeoutMs: 8e3 }
9045
9054
  );
9046
9055
  if (!stdout.trim()) return [];
9047
9056
  const entries = [];
@@ -9520,6 +9529,18 @@ function listWorkspaces() {
9520
9529
  if (valid.length !== all.length) writeAll2(valid);
9521
9530
  return valid.sort((a, b) => a.name.localeCompare(b.name));
9522
9531
  }
9532
+ function isLinkedWorktreeOf(path2, mainRepo) {
9533
+ if (!path2 || path2 === mainRepo) return false;
9534
+ const git2 = (0, import_node_path22.join)(path2, ".git");
9535
+ try {
9536
+ if (!(0, import_node_fs19.existsSync)(git2) || (0, import_node_fs19.statSync)(git2).isDirectory()) return false;
9537
+ const text7 = (0, import_node_fs19.readFileSync)(git2, "utf8");
9538
+ const needle = `${mainRepo.replace(/\/+$/, "")}/.git`;
9539
+ return text7.includes(needle);
9540
+ } catch {
9541
+ return false;
9542
+ }
9543
+ }
9523
9544
  async function addWorkspace(repoPath) {
9524
9545
  const root = await resolveRepoRoot(repoPath);
9525
9546
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
@@ -9528,13 +9549,14 @@ async function addWorkspace(repoPath) {
9528
9549
  await ensureGhPreferOrigin(root);
9529
9550
  const current = readAll2();
9530
9551
  const existing = current.find((w) => w.path === root);
9531
- if (existing) return existing;
9532
- const next = {
9552
+ const withoutLinked = current.filter((w) => !isLinkedWorktreeOf(w.path, root));
9553
+ if (existing && withoutLinked.length === current.length) return existing;
9554
+ const next = existing ?? {
9533
9555
  path: root,
9534
9556
  name: (0, import_node_path22.basename)(root),
9535
9557
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
9536
9558
  };
9537
- writeAll2([...current, next]);
9559
+ writeAll2(existing ? withoutLinked : [...withoutLinked, next]);
9538
9560
  return next;
9539
9561
  }
9540
9562
  function removeWorkspace(repoPath) {
@@ -10647,36 +10669,71 @@ var init_outbound_watch = __esm({
10647
10669
  }
10648
10670
  });
10649
10671
 
10672
+ // src/agents/turn-trace.ts
10673
+ function traceTurn(phase, extra) {
10674
+ try {
10675
+ const line = `${JSON.stringify({ t: (/* @__PURE__ */ new Date()).toISOString(), phase, ...extra })}
10676
+ `;
10677
+ (0, import_node_fs23.appendFileSync)((0, import_node_path27.join)(appDataDir(), "turn-spawn.log"), line);
10678
+ } catch {
10679
+ }
10680
+ }
10681
+ async function withTimeout(promise, ms, label) {
10682
+ let timer;
10683
+ try {
10684
+ return await Promise.race([
10685
+ promise,
10686
+ new Promise((_, reject) => {
10687
+ timer = setTimeout(
10688
+ () => reject(new Error(`${label} timed out after ${ms}ms`)),
10689
+ ms
10690
+ );
10691
+ })
10692
+ ]);
10693
+ } finally {
10694
+ if (timer) clearTimeout(timer);
10695
+ }
10696
+ }
10697
+ var import_node_fs23, import_node_path27;
10698
+ var init_turn_trace = __esm({
10699
+ "src/agents/turn-trace.ts"() {
10700
+ "use strict";
10701
+ import_node_fs23 = require("fs");
10702
+ import_node_path27 = require("path");
10703
+ init_paths();
10704
+ }
10705
+ });
10706
+
10650
10707
  // src/brightsy/config.ts
10651
10708
  function brightsyConfigPath() {
10652
10709
  const override = process.env.BRIGHTSY_CONFIG?.trim();
10653
10710
  if (override) return override;
10654
- return (0, import_node_path27.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
10711
+ return (0, import_node_path28.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
10655
10712
  }
10656
10713
  function loadBrightsyConfig() {
10657
10714
  const path2 = brightsyConfigPath();
10658
- if (!(0, import_node_fs23.existsSync)(path2)) {
10715
+ if (!(0, import_node_fs24.existsSync)(path2)) {
10659
10716
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
10660
10717
  }
10661
- const raw = JSON.parse((0, import_node_fs23.readFileSync)(path2, "utf8"));
10718
+ const raw = JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8"));
10662
10719
  if (!raw.access_token || !raw.account_id) {
10663
10720
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
10664
10721
  }
10665
10722
  return raw;
10666
10723
  }
10667
10724
  function saveBrightsyConfig(cfg) {
10668
- (0, import_node_fs23.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
10725
+ (0, import_node_fs24.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
10669
10726
  `, {
10670
10727
  mode: 384
10671
10728
  });
10672
10729
  }
10673
- var import_node_fs23, import_node_os7, import_node_path27;
10730
+ var import_node_fs24, import_node_os7, import_node_path28;
10674
10731
  var init_config = __esm({
10675
10732
  "src/brightsy/config.ts"() {
10676
10733
  "use strict";
10677
- import_node_fs23 = require("fs");
10734
+ import_node_fs24 = require("fs");
10678
10735
  import_node_os7 = require("os");
10679
- import_node_path27 = require("path");
10736
+ import_node_path28 = require("path");
10680
10737
  }
10681
10738
  });
10682
10739
 
@@ -10903,22 +10960,22 @@ __export(connected_teams_exports, {
10903
10960
  listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
10904
10961
  });
10905
10962
  function storePath4() {
10906
- return (0, import_node_path28.join)(appDataDir(), "brightsy-teams.json");
10963
+ return (0, import_node_path29.join)(appDataDir(), "brightsy-teams.json");
10907
10964
  }
10908
10965
  function readStore4() {
10909
10966
  const path2 = storePath4();
10910
- if (!(0, import_node_fs24.existsSync)(path2)) return [];
10967
+ if (!(0, import_node_fs25.existsSync)(path2)) return [];
10911
10968
  try {
10912
- const parsed = JSON.parse((0, import_node_fs24.readFileSync)(path2, "utf8"));
10969
+ const parsed = JSON.parse((0, import_node_fs25.readFileSync)(path2, "utf8"));
10913
10970
  return Array.isArray(parsed.teams) ? parsed.teams : [];
10914
10971
  } catch {
10915
10972
  return [];
10916
10973
  }
10917
10974
  }
10918
10975
  function writeStore3(teams) {
10919
- (0, import_node_fs24.mkdirSync)(appDataDir(), { recursive: true });
10976
+ (0, import_node_fs25.mkdirSync)(appDataDir(), { recursive: true });
10920
10977
  const path2 = storePath4();
10921
- (0, import_node_fs24.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
10978
+ (0, import_node_fs25.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
10922
10979
  `, {
10923
10980
  mode: 384
10924
10981
  });
@@ -11074,12 +11131,12 @@ function brightsyMcpServerName(slug) {
11074
11131
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
11075
11132
  return `brightsy_${cleaned || "team"}`;
11076
11133
  }
11077
- var import_node_fs24, import_node_path28;
11134
+ var import_node_fs25, import_node_path29;
11078
11135
  var init_connected_teams = __esm({
11079
11136
  "src/brightsy/connected-teams.ts"() {
11080
11137
  "use strict";
11081
- import_node_fs24 = require("fs");
11082
- import_node_path28 = require("path");
11138
+ import_node_fs25 = require("fs");
11139
+ import_node_path29 = require("path");
11083
11140
  init_paths();
11084
11141
  init_accounts();
11085
11142
  init_config();
@@ -11444,11 +11501,11 @@ async function syncCliForTarget(accountId) {
11444
11501
  }
11445
11502
  applyConnectedTeamToCli(team);
11446
11503
  }
11447
- var import_node_fs25, brightsyAdapter;
11504
+ var import_node_fs26, brightsyAdapter;
11448
11505
  var init_brightsy = __esm({
11449
11506
  "src/agents/brightsy.ts"() {
11450
11507
  "use strict";
11451
- import_node_fs25 = require("fs");
11508
+ import_node_fs26 = require("fs");
11452
11509
  init_run();
11453
11510
  init_connected_teams();
11454
11511
  init_config();
@@ -11463,7 +11520,7 @@ var init_brightsy = __esm({
11463
11520
  async detect() {
11464
11521
  const brightsy = resolveAgentExecutable("brightsy");
11465
11522
  if (brightsy !== "brightsy") {
11466
- if (!(0, import_node_fs25.existsSync)(brightsy)) {
11523
+ if (!(0, import_node_fs26.existsSync)(brightsy)) {
11467
11524
  return {
11468
11525
  agent: "brightsy",
11469
11526
  installed: false,
@@ -11571,6 +11628,11 @@ function mcpAllowTools(servers) {
11571
11628
  }
11572
11629
  return out;
11573
11630
  }
11631
+ function mcpAllowToolsFromNames(names) {
11632
+ return mcpAllowTools(
11633
+ [...names].map((name) => name.trim()).filter(Boolean).map((name) => ({ name, connected: true, needsAuth: false }))
11634
+ );
11635
+ }
11574
11636
  function mcpAuthWarnings(servers) {
11575
11637
  const needing = servers.filter((s) => s.needsAuth).map((s) => s.name);
11576
11638
  if (needing.length === 0) return [];
@@ -11639,7 +11701,7 @@ function splitPemCertificates(pem) {
11639
11701
  }
11640
11702
  function readExistingFile(path2) {
11641
11703
  try {
11642
- return (0, import_node_fs26.existsSync)(path2) ? (0, import_node_fs26.readFileSync)(path2, "utf8") : "";
11704
+ return (0, import_node_fs27.existsSync)(path2) ? (0, import_node_fs27.readFileSync)(path2, "utf8") : "";
11643
11705
  } catch {
11644
11706
  return "";
11645
11707
  }
@@ -11671,13 +11733,13 @@ function collectSystemCaPem(io = {}) {
11671
11733
  return "";
11672
11734
  }
11673
11735
  function systemCaBundlePath(io = {}) {
11674
- return (0, import_node_path29.join)((io.appData ?? appDataDir)(), BUNDLE_NAME);
11736
+ return (0, import_node_path30.join)((io.appData ?? appDataDir)(), BUNDLE_NAME);
11675
11737
  }
11676
11738
  function bundleIsFresh(path2, now) {
11677
11739
  try {
11678
- if (!(0, import_node_fs26.existsSync)(path2)) return false;
11679
- if (splitPemCertificates((0, import_node_fs26.readFileSync)(path2, "utf8")).length === 0) return false;
11680
- return now - (0, import_node_fs26.statSync)(path2).mtimeMs < BUNDLE_MAX_AGE_MS;
11740
+ if (!(0, import_node_fs27.existsSync)(path2)) return false;
11741
+ if (splitPemCertificates((0, import_node_fs27.readFileSync)(path2, "utf8")).length === 0) return false;
11742
+ return now - (0, import_node_fs27.statSync)(path2).mtimeMs < BUNDLE_MAX_AGE_MS;
11681
11743
  } catch {
11682
11744
  return false;
11683
11745
  }
@@ -11698,11 +11760,11 @@ function materializeSystemCaBundle(io = {}) {
11698
11760
  if (bundleIsFresh(dest, now)) return dest;
11699
11761
  const pem = collectSystemCaPem(io);
11700
11762
  if (splitPemCertificates(pem).length === 0) {
11701
- return (0, import_node_fs26.existsSync)(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
11763
+ return (0, import_node_fs27.existsSync)(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
11702
11764
  }
11703
11765
  try {
11704
- (0, import_node_fs26.mkdirSync)((0, import_node_path29.dirname)(dest), { recursive: true });
11705
- (0, import_node_fs26.writeFileSync)(dest, pem.endsWith("\n") ? pem : `${pem}
11766
+ (0, import_node_fs27.mkdirSync)((0, import_node_path30.dirname)(dest), { recursive: true });
11767
+ (0, import_node_fs27.writeFileSync)(dest, pem.endsWith("\n") ? pem : `${pem}
11706
11768
  `, { mode: 384 });
11707
11769
  return dest;
11708
11770
  } catch {
@@ -11742,13 +11804,13 @@ function trustSystemCertificates(io = {}) {
11742
11804
  return false;
11743
11805
  }
11744
11806
  }
11745
- var import_node_child_process4, import_node_fs26, import_node_path29, import_node_tls, NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS, BUNDLE_NAME, BUNDLE_MAX_AGE_MS, LINUX_CA_FILES, PEM_CERT_RE;
11807
+ var import_node_child_process4, import_node_fs27, import_node_path30, import_node_tls, NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS, BUNDLE_NAME, BUNDLE_MAX_AGE_MS, LINUX_CA_FILES, PEM_CERT_RE;
11746
11808
  var init_system_ca = __esm({
11747
11809
  "src/http/system-ca.ts"() {
11748
11810
  "use strict";
11749
11811
  import_node_child_process4 = require("child_process");
11750
- import_node_fs26 = require("fs");
11751
- import_node_path29 = require("path");
11812
+ import_node_fs27 = require("fs");
11813
+ import_node_path30 = require("path");
11752
11814
  import_node_tls = __toESM(require("tls"), 1);
11753
11815
  init_paths();
11754
11816
  NODE_USE_SYSTEM_CA = "NODE_USE_SYSTEM_CA";
@@ -11774,43 +11836,43 @@ function electronResourcesPath() {
11774
11836
  function packagedCursorRuntimeDir() {
11775
11837
  const resources = electronResourcesPath();
11776
11838
  if (!resources) return null;
11777
- const dir = (0, import_node_path30.join)(resources, "cursor-runtime");
11778
- if (!(0, import_node_fs27.existsSync)((0, import_node_path30.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
11839
+ const dir = (0, import_node_path31.join)(resources, "cursor-runtime");
11840
+ if (!(0, import_node_fs28.existsSync)((0, import_node_path31.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
11779
11841
  return dir;
11780
11842
  }
11781
11843
  function packagedCursorRunnerPath() {
11782
11844
  const dir = packagedCursorRuntimeDir();
11783
- return dir ? (0, import_node_path30.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
11845
+ return dir ? (0, import_node_path31.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
11784
11846
  }
11785
11847
  function packagedMcpDir() {
11786
11848
  const resources = electronResourcesPath();
11787
11849
  if (!resources) return null;
11788
- const dir = (0, import_node_path30.join)(resources, "sideboard-mcp");
11789
- if (!(0, import_node_fs27.existsSync)((0, import_node_path30.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
11850
+ const dir = (0, import_node_path31.join)(resources, "sideboard-mcp");
11851
+ if (!(0, import_node_fs28.existsSync)((0, import_node_path31.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
11790
11852
  return dir;
11791
11853
  }
11792
11854
  function packagedMcpStdioPath() {
11793
11855
  const dir = packagedMcpDir();
11794
- return dir ? (0, import_node_path30.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
11856
+ return dir ? (0, import_node_path31.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
11795
11857
  }
11796
11858
  function packagedBundledNodePath() {
11797
11859
  const resources = electronResourcesPath();
11798
11860
  if (!resources) return null;
11799
- const bin = (0, import_node_path30.join)(resources, "node", "bin", "node");
11800
- if (!(0, import_node_fs27.existsSync)(bin)) return null;
11861
+ const bin = (0, import_node_path31.join)(resources, "node", "bin", "node");
11862
+ if (!(0, import_node_fs28.existsSync)(bin)) return null;
11801
11863
  return bin;
11802
11864
  }
11803
11865
  function packagedCursorRipgrepCandidate(platformPkg, binName) {
11804
11866
  const dir = packagedCursorRuntimeDir();
11805
11867
  if (!dir) return null;
11806
- return (0, import_node_path30.join)(dir, "node_modules", platformPkg, "bin", binName);
11868
+ return (0, import_node_path31.join)(dir, "node_modules", platformPkg, "bin", binName);
11807
11869
  }
11808
- var import_node_fs27, import_node_path30;
11870
+ var import_node_fs28, import_node_path31;
11809
11871
  var init_packaged_runtime = __esm({
11810
11872
  "src/agents/packaged-runtime.ts"() {
11811
11873
  "use strict";
11812
- import_node_fs27 = require("fs");
11813
- import_node_path30 = require("path");
11874
+ import_node_fs28 = require("fs");
11875
+ import_node_path31 = require("path");
11814
11876
  }
11815
11877
  });
11816
11878
 
@@ -11845,7 +11907,7 @@ function unpackedAsarPath(filePath) {
11845
11907
  if (!isAsarPath(filePath)) return null;
11846
11908
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
11847
11909
  if (unpacked === filePath) return null;
11848
- return (0, import_node_fs28.existsSync)(unpacked) ? unpacked : null;
11910
+ return (0, import_node_fs29.existsSync)(unpacked) ? unpacked : null;
11849
11911
  }
11850
11912
  function nodeReadableScriptPath(scriptPath) {
11851
11913
  return unpackedAsarPath(scriptPath) ?? scriptPath;
@@ -11885,37 +11947,37 @@ function pickPreferredNode(candidates) {
11885
11947
  return best;
11886
11948
  }
11887
11949
  function versionDirNodeBins(root, toBin) {
11888
- if (!(0, import_node_fs28.existsSync)(root)) return [];
11950
+ if (!(0, import_node_fs29.existsSync)(root)) return [];
11889
11951
  try {
11890
- return (0, import_node_fs28.readdirSync)(root).map(toBin);
11952
+ return (0, import_node_fs29.readdirSync)(root).map(toBin);
11891
11953
  } catch {
11892
11954
  return [];
11893
11955
  }
11894
11956
  }
11895
11957
  function defaultNodeBinCandidates(home = (0, import_node_os8.homedir)()) {
11896
11958
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
11897
- (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path31.join)(prefix, "opt", `node@${major}`, "bin", "node"))
11959
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path32.join)(prefix, "opt", `node@${major}`, "bin", "node"))
11898
11960
  );
11899
11961
  return [
11900
11962
  ...kegs,
11901
11963
  "/opt/homebrew/bin/node",
11902
11964
  "/usr/local/bin/node",
11903
- (0, import_node_path31.join)(home, ".local/share/fnm/aliases/default/bin/node"),
11904
- (0, import_node_path31.join)(home, ".nvm/current/bin/node"),
11905
- (0, import_node_path31.join)(home, ".volta/bin/node"),
11906
- (0, import_node_path31.join)(home, ".asdf/shims/node"),
11907
- (0, import_node_path31.join)(home, ".local/share/mise/shims/node"),
11965
+ (0, import_node_path32.join)(home, ".local/share/fnm/aliases/default/bin/node"),
11966
+ (0, import_node_path32.join)(home, ".nvm/current/bin/node"),
11967
+ (0, import_node_path32.join)(home, ".volta/bin/node"),
11968
+ (0, import_node_path32.join)(home, ".asdf/shims/node"),
11969
+ (0, import_node_path32.join)(home, ".local/share/mise/shims/node"),
11908
11970
  ...versionDirNodeBins(
11909
- (0, import_node_path31.join)(home, ".nvm", "versions", "node"),
11910
- (name) => (0, import_node_path31.join)(home, ".nvm", "versions", "node", name, "bin", "node")
11971
+ (0, import_node_path32.join)(home, ".nvm", "versions", "node"),
11972
+ (name) => (0, import_node_path32.join)(home, ".nvm", "versions", "node", name, "bin", "node")
11911
11973
  ),
11912
11974
  ...versionDirNodeBins(
11913
- (0, import_node_path31.join)(home, ".local/share/fnm", "node-versions"),
11914
- (name) => (0, import_node_path31.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
11975
+ (0, import_node_path32.join)(home, ".local/share/fnm", "node-versions"),
11976
+ (name) => (0, import_node_path32.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
11915
11977
  ),
11916
11978
  ...versionDirNodeBins(
11917
- (0, import_node_path31.join)(home, ".volta", "tools", "image", "node"),
11918
- (name) => (0, import_node_path31.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
11979
+ (0, import_node_path32.join)(home, ".volta", "tools", "image", "node"),
11980
+ (name) => (0, import_node_path32.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
11919
11981
  )
11920
11982
  ];
11921
11983
  }
@@ -11924,10 +11986,10 @@ function uniqueExistingNodeBins(paths) {
11924
11986
  const out = [];
11925
11987
  for (const raw of paths) {
11926
11988
  const p = raw.trim();
11927
- if (!p || !(0, import_node_fs28.existsSync)(p) || isElectronLikeCommand(p)) continue;
11989
+ if (!p || !(0, import_node_fs29.existsSync)(p) || isElectronLikeCommand(p)) continue;
11928
11990
  let key = p;
11929
11991
  try {
11930
- key = (0, import_node_fs28.realpathSync)(p);
11992
+ key = (0, import_node_fs29.realpathSync)(p);
11931
11993
  } catch {
11932
11994
  continue;
11933
11995
  }
@@ -12007,13 +12069,13 @@ async function resolveNodeLaunch(scriptPath) {
12007
12069
  env: { ELECTRON_RUN_AS_NODE: "1" }
12008
12070
  };
12009
12071
  }
12010
- var import_node_fs28, import_node_os8, import_node_path31, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
12072
+ var import_node_fs29, import_node_os8, import_node_path32, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
12011
12073
  var init_node_launch = __esm({
12012
12074
  "src/agents/node-launch.ts"() {
12013
12075
  "use strict";
12014
- import_node_fs28 = require("fs");
12076
+ import_node_fs29 = require("fs");
12015
12077
  import_node_os8 = require("os");
12016
- import_node_path31 = require("path");
12078
+ import_node_path32 = require("path");
12017
12079
  init_nested_electron_env();
12018
12080
  init_system_ca();
12019
12081
  init_run();
@@ -12115,37 +12177,37 @@ function corePackageDir() {
12115
12177
  try {
12116
12178
  const url = import_meta.url;
12117
12179
  if (typeof url === "string" && url.length > 0) {
12118
- return (0, import_node_path32.dirname)((0, import_node_url.fileURLToPath)(url));
12180
+ return (0, import_node_path33.dirname)((0, import_node_url.fileURLToPath)(url));
12119
12181
  }
12120
12182
  } catch {
12121
12183
  }
12122
12184
  try {
12123
- const req = (0, import_node_module.createRequire)((0, import_node_path32.join)(process.cwd(), "package.json"));
12124
- return (0, import_node_path32.dirname)(req.resolve("@sideboard-ai/core"));
12185
+ const req = (0, import_node_module.createRequire)((0, import_node_path33.join)(process.cwd(), "package.json"));
12186
+ return (0, import_node_path33.dirname)(req.resolve("@sideboard-ai/core"));
12125
12187
  } catch {
12126
12188
  return process.cwd();
12127
12189
  }
12128
12190
  }
12129
12191
  function findSideboardMcpJsEntry() {
12130
12192
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
12131
- if (override && (0, import_node_fs29.existsSync)(override)) return override;
12193
+ if (override && (0, import_node_fs30.existsSync)(override)) return override;
12132
12194
  const packaged = packagedMcpStdioPath();
12133
12195
  if (packaged) return packaged;
12134
12196
  let dir = corePackageDir();
12135
12197
  for (let i = 0; i < 10; i++) {
12136
12198
  const candidates = [
12137
- (0, import_node_path32.join)(dir, "mcp/run-stdio.js"),
12138
- (0, import_node_path32.join)(dir, "mcp/run-stdio.cjs"),
12139
- (0, import_node_path32.join)(dir, "dist/mcp/run-stdio.js"),
12140
- (0, import_node_path32.join)(dir, "dist/mcp/run-stdio.cjs"),
12141
- (0, import_node_path32.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
12142
- (0, import_node_path32.join)(dir, "packages/cli/dist/index.js"),
12143
- (0, import_node_path32.join)(dir, "cli/dist/index.js")
12199
+ (0, import_node_path33.join)(dir, "mcp/run-stdio.js"),
12200
+ (0, import_node_path33.join)(dir, "mcp/run-stdio.cjs"),
12201
+ (0, import_node_path33.join)(dir, "dist/mcp/run-stdio.js"),
12202
+ (0, import_node_path33.join)(dir, "dist/mcp/run-stdio.cjs"),
12203
+ (0, import_node_path33.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
12204
+ (0, import_node_path33.join)(dir, "packages/cli/dist/index.js"),
12205
+ (0, import_node_path33.join)(dir, "cli/dist/index.js")
12144
12206
  ];
12145
12207
  for (const p of candidates) {
12146
- if ((0, import_node_fs29.existsSync)(p) && !isAsarPath(p)) return p;
12208
+ if ((0, import_node_fs30.existsSync)(p) && !isAsarPath(p)) return p;
12147
12209
  }
12148
- const parent = (0, import_node_path32.dirname)(dir);
12210
+ const parent = (0, import_node_path33.dirname)(dir);
12149
12211
  if (parent === dir) break;
12150
12212
  dir = parent;
12151
12213
  }
@@ -12292,22 +12354,22 @@ function writeMcpServersConfig(servers) {
12292
12354
  ...env ? { env } : {}
12293
12355
  };
12294
12356
  }
12295
- const dir = (0, import_node_fs29.mkdtempSync)((0, import_node_path32.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
12296
- const cfgPath = (0, import_node_path32.join)(dir, "mcp.json");
12297
- (0, import_node_fs29.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
12357
+ const dir = (0, import_node_fs30.mkdtempSync)((0, import_node_path33.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
12358
+ const cfgPath = (0, import_node_path33.join)(dir, "mcp.json");
12359
+ (0, import_node_fs30.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
12298
12360
  return cfgPath;
12299
12361
  }
12300
12362
  async function writeInjectedMcpConfig(opts) {
12301
12363
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
12302
12364
  }
12303
- var import_node_fs29, import_node_module, import_node_os9, import_node_path32, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
12365
+ var import_node_fs30, import_node_module, import_node_os9, import_node_path33, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, SIDEBOARD_GITHUB_MCP_ALLOWED_TOOLS, SIDEBOARD_LINEAR_MCP_ALLOWED_TOOLS, SIDEBOARD_ABLETIME_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
12304
12366
  var init_injected_mcp = __esm({
12305
12367
  "src/agents/injected-mcp.ts"() {
12306
12368
  "use strict";
12307
- import_node_fs29 = require("fs");
12369
+ import_node_fs30 = require("fs");
12308
12370
  import_node_module = require("module");
12309
12371
  import_node_os9 = require("os");
12310
- import_node_path32 = require("path");
12372
+ import_node_path33 = require("path");
12311
12373
  import_node_url = require("url");
12312
12374
  init_run();
12313
12375
  init_config();
@@ -12347,6 +12409,195 @@ var init_injected_mcp = __esm({
12347
12409
  }
12348
12410
  });
12349
12411
 
12412
+ // src/agents/user-mcp-config.ts
12413
+ function userCursorMcpConfigPath() {
12414
+ return (0, import_node_path34.join)((0, import_node_os10.homedir)(), ".cursor", "mcp.json");
12415
+ }
12416
+ function userClaudeMcpConfigPath() {
12417
+ return (0, import_node_path34.join)((0, import_node_os10.homedir)(), ".claude.json");
12418
+ }
12419
+ function asObject(value) {
12420
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
12421
+ return { ...value };
12422
+ }
12423
+ function stripElectronSpawnEnv(env) {
12424
+ if (!env) return void 0;
12425
+ const next = { ...env };
12426
+ delete next.ELECTRON_RUN_AS_NODE;
12427
+ delete next.ELECTRON_RUN_AS_NODE;
12428
+ return Object.keys(next).length > 0 ? next : void 0;
12429
+ }
12430
+ function mergeSideboardIntoMcpServersJson(existing, sideboard) {
12431
+ const root = asObject(existing);
12432
+ const servers = asObject(root.mcpServers);
12433
+ const env = stripElectronSpawnEnv(sideboard.env);
12434
+ servers.sideboard = {
12435
+ type: "stdio",
12436
+ command: sideboard.command,
12437
+ ...sideboard.args && sideboard.args.length > 0 ? { args: sideboard.args } : {},
12438
+ ...env ? { env } : {}
12439
+ };
12440
+ return { ...root, mcpServers: servers };
12441
+ }
12442
+ function writeMergedMcpServersJson(configPath, sideboard) {
12443
+ let existing = {};
12444
+ if ((0, import_node_fs31.existsSync)(configPath)) {
12445
+ try {
12446
+ existing = JSON.parse((0, import_node_fs31.readFileSync)(configPath, "utf8"));
12447
+ } catch {
12448
+ existing = {};
12449
+ }
12450
+ }
12451
+ const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
12452
+ (0, import_node_fs31.mkdirSync)((0, import_node_path34.dirname)(configPath), { recursive: true });
12453
+ (0, import_node_fs31.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
12454
+ `);
12455
+ }
12456
+ function launchFromResolved(server) {
12457
+ return {
12458
+ command: server.command,
12459
+ args: server.args,
12460
+ env: {
12461
+ ...server.env ?? {},
12462
+ SIDEBOARD_APP_DATA: appDataDir()
12463
+ }
12464
+ };
12465
+ }
12466
+ async function registerPackagedUserMcpClients() {
12467
+ const launch = launchFromResolved(await resolveSideboardMcpServer());
12468
+ const cursor = userCursorMcpConfigPath();
12469
+ writeMergedMcpServersJson(cursor, launch);
12470
+ const claude = userClaudeMcpConfigPath();
12471
+ if ((0, import_node_fs31.existsSync)(claude)) {
12472
+ writeMergedMcpServersJson(claude, launch);
12473
+ return { cursor, claude };
12474
+ }
12475
+ return { cursor };
12476
+ }
12477
+ var import_node_fs31, import_node_os10, import_node_path34;
12478
+ var init_user_mcp_config = __esm({
12479
+ "src/agents/user-mcp-config.ts"() {
12480
+ "use strict";
12481
+ import_node_fs31 = require("fs");
12482
+ import_node_os10 = require("os");
12483
+ import_node_path34 = require("path");
12484
+ init_paths();
12485
+ init_injected_mcp();
12486
+ }
12487
+ });
12488
+
12489
+ // src/agents/orch-mcp-isolation.ts
12490
+ function isInjectedOrchMcpName(name) {
12491
+ const n = name.trim().toLowerCase();
12492
+ return n === "sideboard" || n === "brightsy" || n.startsWith("brightsy_");
12493
+ }
12494
+ function asObject2(value) {
12495
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
12496
+ return value;
12497
+ }
12498
+ function listMcpNamesFromJsonMap(raw, key) {
12499
+ return Object.keys(asObject2(asObject2(raw)[key])).filter((n) => n.trim());
12500
+ }
12501
+ function listMcpNamesFromCodexToml(text7) {
12502
+ try {
12503
+ const parsed = (0, import_smol_toml2.parse)(text7);
12504
+ return Object.keys(asObject2(parsed.mcp_servers)).filter((n) => n.trim());
12505
+ } catch {
12506
+ return [];
12507
+ }
12508
+ }
12509
+ function readJsonObject(path2) {
12510
+ try {
12511
+ return JSON.parse((0, import_node_fs32.readFileSync)(path2, "utf8"));
12512
+ } catch {
12513
+ return {};
12514
+ }
12515
+ }
12516
+ function readText(path2) {
12517
+ try {
12518
+ return (0, import_node_fs32.readFileSync)(path2, "utf8");
12519
+ } catch {
12520
+ return "";
12521
+ }
12522
+ }
12523
+ function userCodexConfigPaths(home = (0, import_node_os11.homedir)()) {
12524
+ return [(0, import_node_path35.join)(home, ".codex", "config.toml"), (0, import_node_path35.join)(home, ".config", "codex", "config.toml")];
12525
+ }
12526
+ function userOpencodeConfigPaths(home = (0, import_node_os11.homedir)()) {
12527
+ return [
12528
+ (0, import_node_path35.join)(home, ".config", "opencode", "opencode.json"),
12529
+ (0, import_node_path35.join)(home, ".config", "opencode", "opencode.jsonc")
12530
+ ];
12531
+ }
12532
+ function userMcpNamesToDisable(opts) {
12533
+ const keep = new Set(
12534
+ [...opts.injectedNames ?? []].map((n) => n.trim().toLowerCase()).filter(Boolean)
12535
+ );
12536
+ const out = [];
12537
+ const seen = /* @__PURE__ */ new Set();
12538
+ for (const raw of opts.names) {
12539
+ const name = raw.trim();
12540
+ if (!name) continue;
12541
+ const key = name.toLowerCase();
12542
+ if (seen.has(key) || keep.has(key) || isInjectedOrchMcpName(name)) continue;
12543
+ seen.add(key);
12544
+ out.push(name);
12545
+ }
12546
+ return out;
12547
+ }
12548
+ function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
12549
+ const names = [];
12550
+ for (const path2 of userCodexConfigPaths(home)) {
12551
+ if (!(0, import_node_fs32.existsSync)(path2)) continue;
12552
+ names.push(...listMcpNamesFromCodexToml(readText(path2)));
12553
+ }
12554
+ return names;
12555
+ }
12556
+ function listUserOpencodeMcpNames(home = (0, import_node_os11.homedir)()) {
12557
+ const names = [];
12558
+ for (const path2 of userOpencodeConfigPaths(home)) {
12559
+ if (!(0, import_node_fs32.existsSync)(path2)) continue;
12560
+ names.push(...listMcpNamesFromJsonMap(readJsonObject(path2), "mcp"));
12561
+ }
12562
+ return names;
12563
+ }
12564
+ function listUserClaudeMcpNames(home = (0, import_node_os11.homedir)()) {
12565
+ const claudePath = home === (0, import_node_os11.homedir)() ? userClaudeMcpConfigPath() : (0, import_node_path35.join)(home, ".claude.json");
12566
+ if (!(0, import_node_fs32.existsSync)(claudePath)) return [];
12567
+ return listMcpNamesFromJsonMap(readJsonObject(claudePath), "mcpServers");
12568
+ }
12569
+ function toCodexDisableUserMcpArgs(names) {
12570
+ const args = [];
12571
+ for (const name of names) {
12572
+ if (!/^[A-Za-z0-9_-]+$/.test(name)) continue;
12573
+ args.push("-c", `mcp_servers.${name}.enabled=false`);
12574
+ }
12575
+ return args;
12576
+ }
12577
+ function toCodexUnattendedAppsArgs() {
12578
+ return [
12579
+ "-c",
12580
+ "features.apps=false",
12581
+ "-c",
12582
+ "apps._default.enabled=false",
12583
+ "-c",
12584
+ "apps.posthog.enabled=false",
12585
+ "-c",
12586
+ "features.plugins=false"
12587
+ ];
12588
+ }
12589
+ var import_node_fs32, import_node_os11, import_node_path35, import_smol_toml2;
12590
+ var init_orch_mcp_isolation = __esm({
12591
+ "src/agents/orch-mcp-isolation.ts"() {
12592
+ "use strict";
12593
+ import_node_fs32 = require("fs");
12594
+ import_node_os11 = require("os");
12595
+ import_node_path35 = require("path");
12596
+ import_smol_toml2 = require("smol-toml");
12597
+ init_user_mcp_config();
12598
+ }
12599
+ });
12600
+
12350
12601
  // src/agents/types.ts
12351
12602
  function permissionMode(thread) {
12352
12603
  if (thread.sourceType === "orchestration") {
@@ -12395,16 +12646,8 @@ var init_types = __esm({
12395
12646
  });
12396
12647
 
12397
12648
  // src/agents/claude.ts
12398
- async function loadMcpServers() {
12399
- if (mcpListCache && Date.now() - mcpListCache.at < 3e4) {
12400
- return mcpListCache.servers;
12401
- }
12402
- const claude = resolveClaudeExecutable();
12403
- const mcpText = await run(claude, ["mcp", "list"], { reject: false });
12404
- const servers = parseMcpList(`${mcpText.stdout}
12405
- ${mcpText.stderr}`);
12406
- mcpListCache = { at: Date.now(), servers };
12407
- return servers;
12649
+ function isLocalDevAppDataDir(dir = process.env.SIDEBOARD_APP_DATA) {
12650
+ return /[/\\]\.sideboard[/\\]dev-app-data(?:[/\\]|$)/.test(dir ?? "");
12408
12651
  }
12409
12652
  function usageFromClaude(usage) {
12410
12653
  if (!usage) return null;
@@ -12712,14 +12955,15 @@ function parseIssuesJson(raw) {
12712
12955
  }
12713
12956
  return [];
12714
12957
  }
12715
- var import_node_fs30, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
12958
+ var import_node_fs33, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
12716
12959
  var init_claude = __esm({
12717
12960
  "src/agents/claude.ts"() {
12718
12961
  "use strict";
12719
- import_node_fs30 = require("fs");
12962
+ import_node_fs33 = require("fs");
12720
12963
  init_run();
12721
12964
  init_app_settings();
12722
12965
  init_claude_mcp();
12966
+ init_orch_mcp_isolation();
12723
12967
  init_error_detail();
12724
12968
  init_message_parts();
12725
12969
  init_injected_mcp();
@@ -12750,13 +12994,12 @@ var init_claude = __esm({
12750
12994
  "Skill(claude-in-chrome)"
12751
12995
  ];
12752
12996
  CLAUDE_PROMPT_ARG_MAX = 2e5;
12753
- mcpListCache = null;
12754
12997
  claudeAdapter = {
12755
12998
  kind: "claude",
12756
12999
  async detect() {
12757
13000
  const claude = resolveClaudeExecutable();
12758
13001
  if (claude !== "claude") {
12759
- if (!(0, import_node_fs30.existsSync)(claude)) {
13002
+ if (!(0, import_node_fs33.existsSync)(claude)) {
12760
13003
  return {
12761
13004
  agent: "claude",
12762
13005
  installed: false,
@@ -12824,10 +13067,9 @@ var init_claude = __esm({
12824
13067
  ...brightsyMcpAllowedTools(injectedBrightsyNames)
12825
13068
  ];
12826
13069
  } else {
12827
- const servers = await loadMcpServers();
12828
13070
  allowedTools = [
12829
13071
  ...BASE_ALLOWED_TOOLS,
12830
- ...mcpAllowTools(servers),
13072
+ ...mcpAllowToolsFromNames(userMcpNamesToDisable({ names: listUserClaudeMcpNames() })),
12831
13073
  ...sideboardWorktreeAllowedTools({
12832
13074
  github: true,
12833
13075
  linear: isLinearConnected(),
@@ -12855,9 +13097,7 @@ var init_claude = __esm({
12855
13097
  const mcpConfigPath = writeMcpServersConfig(injectedServers);
12856
13098
  if (mcpConfigPath) {
12857
13099
  args.push("--mcp-config", mcpConfigPath);
12858
- if (isOrchestrator) {
12859
- args.push("--strict-mcp-config");
12860
- }
13100
+ args.push("--strict-mcp-config");
12861
13101
  }
12862
13102
  if (chromeOn) {
12863
13103
  args.push("--chrome");
@@ -12889,8 +13129,10 @@ var init_claude = __esm({
12889
13129
  CLAUDE_CODE_FORWARD_SUBAGENT_TEXT: "1",
12890
13130
  CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS: process.env.CLAUDE_CODE_PRINT_BG_WAIT_CEILING_MS ?? String(CLAUDE_PRINT_BG_WAIT_CEILING_MS),
12891
13131
  // `--strict-mcp-config` still fetches claude.ai connectors on some CLI
12892
- // builds (anthropics/claude-code#60252). Coordinators do not need them.
12893
- ...isOrchestrator ? { ENABLE_CLAUDEAI_MCP_SERVERS: "false" } : {}
13132
+ // builds (anthropics/claude-code#60252). Coordinators never need them.
13133
+ // Local `pnpm dev` also disables them: those HTTP connectors hang the
13134
+ // first worktree turn when Electron's cwd is this Sideboard repo.
13135
+ ...isOrchestrator || isLocalDevAppDataDir() ? { ENABLE_CLAUDEAI_MCP_SERVERS: "false" } : {}
12894
13136
  }
12895
13137
  };
12896
13138
  },
@@ -12952,249 +13194,65 @@ var init_claude = __esm({
12952
13194
  if (delta?.text) return withEventParentId({ type: "stdout", data: delta.text }, parentId);
12953
13195
  if (delta?.thinking) {
12954
13196
  return withEventParentId({ type: "thinking", data: delta.thinking }, parentId);
12955
- }
12956
- return null;
12957
- }
12958
- if (obj.type === "result") {
12959
- const events = [];
12960
- const errorDetail = claudeResultErrorDetail(obj);
12961
- if (errorDetail) {
12962
- events.push({ type: "stderr", data: errorDetail });
12963
- } else {
12964
- const text7 = obj.result;
12965
- if (typeof text7 === "string" && text7) events.push({ type: "stdout", data: text7 });
12966
- }
12967
- const usage = usageFromClaude(obj.usage);
12968
- if (usage) {
12969
- const costUsd = costUsdFromClaudeResult(obj);
12970
- if (costUsd != null) usage.costUsd = costUsd;
12971
- events.push({ type: "usage", data: usage, scope: "turn" });
12972
- }
12973
- if (events.length === 0) return null;
12974
- return events.length === 1 ? events[0] : events;
12975
- }
12976
- return null;
12977
- } catch {
12978
- return { type: "stdout", data: line };
12979
- }
12980
- },
12981
- async resolveSessionId(_worktreePath, cached) {
12982
- return cached;
12983
- },
12984
- async buildAttach(thread) {
12985
- const claude = resolveClaudeExecutable();
12986
- const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
12987
- const args = sessionId ? ["--resume", sessionId] : [];
12988
- if (claudeChromeEnabled()) {
12989
- args.push("--chrome");
12990
- }
12991
- return { file: claude, args, cwd: thread.worktreePath };
12992
- },
12993
- async listLinearIssues(_repoPath) {
12994
- const claude = resolveClaudeExecutable();
12995
- const prompt = "List my assigned Linear issues as JSON array only, no markdown. Each item: id, identifier, title, url, labels (string[]).";
12996
- const { stdout, exitCode } = await run(
12997
- claude,
12998
- [
12999
- "-p",
13000
- prompt,
13001
- "--output-format",
13002
- "json",
13003
- "--permission-mode",
13004
- "bypassPermissions",
13005
- "--allowedTools",
13006
- "mcp__linear__*"
13007
- ],
13008
- { reject: false }
13009
- );
13010
- if (exitCode !== 0) return [];
13011
- return parseIssuesJson(stdout);
13012
- }
13013
- };
13014
- }
13015
- });
13016
-
13017
- // src/agents/user-mcp-config.ts
13018
- function userCursorMcpConfigPath() {
13019
- return (0, import_node_path33.join)((0, import_node_os10.homedir)(), ".cursor", "mcp.json");
13020
- }
13021
- function userClaudeMcpConfigPath() {
13022
- return (0, import_node_path33.join)((0, import_node_os10.homedir)(), ".claude.json");
13023
- }
13024
- function asObject(value) {
13025
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
13026
- return { ...value };
13027
- }
13028
- function stripElectronSpawnEnv(env) {
13029
- if (!env) return void 0;
13030
- const next = { ...env };
13031
- delete next.ELECTRON_RUN_AS_NODE;
13032
- delete next.ELECTRON_RUN_AS_NODE;
13033
- return Object.keys(next).length > 0 ? next : void 0;
13034
- }
13035
- function mergeSideboardIntoMcpServersJson(existing, sideboard) {
13036
- const root = asObject(existing);
13037
- const servers = asObject(root.mcpServers);
13038
- const env = stripElectronSpawnEnv(sideboard.env);
13039
- servers.sideboard = {
13040
- type: "stdio",
13041
- command: sideboard.command,
13042
- ...sideboard.args && sideboard.args.length > 0 ? { args: sideboard.args } : {},
13043
- ...env ? { env } : {}
13044
- };
13045
- return { ...root, mcpServers: servers };
13046
- }
13047
- function writeMergedMcpServersJson(configPath, sideboard) {
13048
- let existing = {};
13049
- if ((0, import_node_fs31.existsSync)(configPath)) {
13050
- try {
13051
- existing = JSON.parse((0, import_node_fs31.readFileSync)(configPath, "utf8"));
13052
- } catch {
13053
- existing = {};
13054
- }
13055
- }
13056
- const next = mergeSideboardIntoMcpServersJson(existing, sideboard);
13057
- (0, import_node_fs31.mkdirSync)((0, import_node_path33.dirname)(configPath), { recursive: true });
13058
- (0, import_node_fs31.writeFileSync)(configPath, `${JSON.stringify(next, null, 2)}
13059
- `);
13060
- }
13061
- function launchFromResolved(server) {
13062
- return {
13063
- command: server.command,
13064
- args: server.args,
13065
- env: {
13066
- ...server.env ?? {},
13067
- SIDEBOARD_APP_DATA: appDataDir()
13068
- }
13069
- };
13070
- }
13071
- async function registerPackagedUserMcpClients() {
13072
- const launch = launchFromResolved(await resolveSideboardMcpServer());
13073
- const cursor = userCursorMcpConfigPath();
13074
- writeMergedMcpServersJson(cursor, launch);
13075
- const claude = userClaudeMcpConfigPath();
13076
- if ((0, import_node_fs31.existsSync)(claude)) {
13077
- writeMergedMcpServersJson(claude, launch);
13078
- return { cursor, claude };
13079
- }
13080
- return { cursor };
13081
- }
13082
- var import_node_fs31, import_node_os10, import_node_path33;
13083
- var init_user_mcp_config = __esm({
13084
- "src/agents/user-mcp-config.ts"() {
13085
- "use strict";
13086
- import_node_fs31 = require("fs");
13087
- import_node_os10 = require("os");
13088
- import_node_path33 = require("path");
13089
- init_paths();
13090
- init_injected_mcp();
13091
- }
13092
- });
13093
-
13094
- // src/agents/orch-mcp-isolation.ts
13095
- function isInjectedOrchMcpName(name) {
13096
- const n = name.trim().toLowerCase();
13097
- return n === "sideboard" || n === "brightsy" || n.startsWith("brightsy_");
13098
- }
13099
- function asObject2(value) {
13100
- if (!value || typeof value !== "object" || Array.isArray(value)) return {};
13101
- return value;
13102
- }
13103
- function listMcpNamesFromJsonMap(raw, key) {
13104
- return Object.keys(asObject2(asObject2(raw)[key])).filter((n) => n.trim());
13105
- }
13106
- function listMcpNamesFromCodexToml(text7) {
13107
- try {
13108
- const parsed = (0, import_smol_toml2.parse)(text7);
13109
- return Object.keys(asObject2(parsed.mcp_servers)).filter((n) => n.trim());
13110
- } catch {
13111
- return [];
13112
- }
13113
- }
13114
- function readJsonObject(path2) {
13115
- try {
13116
- return JSON.parse((0, import_node_fs32.readFileSync)(path2, "utf8"));
13117
- } catch {
13118
- return {};
13119
- }
13120
- }
13121
- function readText(path2) {
13122
- try {
13123
- return (0, import_node_fs32.readFileSync)(path2, "utf8");
13124
- } catch {
13125
- return "";
13126
- }
13127
- }
13128
- function userCodexConfigPaths(home = (0, import_node_os11.homedir)()) {
13129
- return [(0, import_node_path34.join)(home, ".codex", "config.toml"), (0, import_node_path34.join)(home, ".config", "codex", "config.toml")];
13130
- }
13131
- function userOpencodeConfigPaths(home = (0, import_node_os11.homedir)()) {
13132
- return [
13133
- (0, import_node_path34.join)(home, ".config", "opencode", "opencode.json"),
13134
- (0, import_node_path34.join)(home, ".config", "opencode", "opencode.jsonc")
13135
- ];
13136
- }
13137
- function userMcpNamesToDisable(opts) {
13138
- const keep = new Set(
13139
- [...opts.injectedNames ?? []].map((n) => n.trim().toLowerCase()).filter(Boolean)
13140
- );
13141
- const out = [];
13142
- const seen = /* @__PURE__ */ new Set();
13143
- for (const raw of opts.names) {
13144
- const name = raw.trim();
13145
- if (!name) continue;
13146
- const key = name.toLowerCase();
13147
- if (seen.has(key) || keep.has(key) || isInjectedOrchMcpName(name)) continue;
13148
- seen.add(key);
13149
- out.push(name);
13150
- }
13151
- return out;
13152
- }
13153
- function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
13154
- const names = [];
13155
- for (const path2 of userCodexConfigPaths(home)) {
13156
- if (!(0, import_node_fs32.existsSync)(path2)) continue;
13157
- names.push(...listMcpNamesFromCodexToml(readText(path2)));
13158
- }
13159
- return names;
13160
- }
13161
- function listUserOpencodeMcpNames(home = (0, import_node_os11.homedir)()) {
13162
- const names = [];
13163
- for (const path2 of userOpencodeConfigPaths(home)) {
13164
- if (!(0, import_node_fs32.existsSync)(path2)) continue;
13165
- names.push(...listMcpNamesFromJsonMap(readJsonObject(path2), "mcp"));
13166
- }
13167
- return names;
13168
- }
13169
- function toCodexDisableUserMcpArgs(names) {
13170
- const args = [];
13171
- for (const name of names) {
13172
- if (!/^[A-Za-z0-9_-]+$/.test(name)) continue;
13173
- args.push("-c", `mcp_servers.${name}.enabled=false`);
13174
- }
13175
- return args;
13176
- }
13177
- function toCodexUnattendedAppsArgs() {
13178
- return [
13179
- "-c",
13180
- "features.apps=false",
13181
- "-c",
13182
- "apps._default.enabled=false",
13183
- "-c",
13184
- "apps.posthog.enabled=false",
13185
- "-c",
13186
- "features.plugins=false"
13187
- ];
13188
- }
13189
- var import_node_fs32, import_node_os11, import_node_path34, import_smol_toml2;
13190
- var init_orch_mcp_isolation = __esm({
13191
- "src/agents/orch-mcp-isolation.ts"() {
13192
- "use strict";
13193
- import_node_fs32 = require("fs");
13194
- import_node_os11 = require("os");
13195
- import_node_path34 = require("path");
13196
- import_smol_toml2 = require("smol-toml");
13197
- init_user_mcp_config();
13197
+ }
13198
+ return null;
13199
+ }
13200
+ if (obj.type === "result") {
13201
+ const events = [];
13202
+ const errorDetail = claudeResultErrorDetail(obj);
13203
+ if (errorDetail) {
13204
+ events.push({ type: "stderr", data: errorDetail });
13205
+ } else {
13206
+ const text7 = obj.result;
13207
+ if (typeof text7 === "string" && text7) events.push({ type: "stdout", data: text7 });
13208
+ }
13209
+ const usage = usageFromClaude(obj.usage);
13210
+ if (usage) {
13211
+ const costUsd = costUsdFromClaudeResult(obj);
13212
+ if (costUsd != null) usage.costUsd = costUsd;
13213
+ events.push({ type: "usage", data: usage, scope: "turn" });
13214
+ }
13215
+ if (events.length === 0) return null;
13216
+ return events.length === 1 ? events[0] : events;
13217
+ }
13218
+ return null;
13219
+ } catch {
13220
+ return { type: "stdout", data: line };
13221
+ }
13222
+ },
13223
+ async resolveSessionId(_worktreePath, cached) {
13224
+ return cached;
13225
+ },
13226
+ async buildAttach(thread) {
13227
+ const claude = resolveClaudeExecutable();
13228
+ const sessionId = await this.resolveSessionId(thread.worktreePath, thread.sessionId);
13229
+ const args = sessionId ? ["--resume", sessionId] : [];
13230
+ if (claudeChromeEnabled()) {
13231
+ args.push("--chrome");
13232
+ }
13233
+ return { file: claude, args, cwd: thread.worktreePath };
13234
+ },
13235
+ async listLinearIssues(_repoPath) {
13236
+ const claude = resolveClaudeExecutable();
13237
+ const prompt = "List my assigned Linear issues as JSON array only, no markdown. Each item: id, identifier, title, url, labels (string[]).";
13238
+ const { stdout, exitCode } = await run(
13239
+ claude,
13240
+ [
13241
+ "-p",
13242
+ prompt,
13243
+ "--output-format",
13244
+ "json",
13245
+ "--permission-mode",
13246
+ "bypassPermissions",
13247
+ "--allowedTools",
13248
+ "mcp__linear__*"
13249
+ ],
13250
+ { reject: false }
13251
+ );
13252
+ if (exitCode !== 0) return [];
13253
+ return parseIssuesJson(stdout);
13254
+ }
13255
+ };
13198
13256
  }
13199
13257
  });
13200
13258
 
@@ -13208,7 +13266,7 @@ async function listCodexModels() {
13208
13266
  if (codex === "codex") {
13209
13267
  const which = await run("which", ["codex"], { reject: false });
13210
13268
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
13211
- } else if (!(0, import_node_fs33.existsSync)(codex)) {
13269
+ } else if (!(0, import_node_fs34.existsSync)(codex)) {
13212
13270
  return FALLBACK_CODEX_MODELS;
13213
13271
  }
13214
13272
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -13243,12 +13301,12 @@ function usageFromCodex(usage) {
13243
13301
  }
13244
13302
  function codexConfigHasNetworkAccess() {
13245
13303
  const candidates = [
13246
- (0, import_node_path35.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
13247
- (0, import_node_path35.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
13304
+ (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
13305
+ (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
13248
13306
  ];
13249
13307
  for (const path2 of candidates) {
13250
- if (!(0, import_node_fs33.existsSync)(path2)) continue;
13251
- const text7 = (0, import_node_fs33.readFileSync)(path2, "utf8");
13308
+ if (!(0, import_node_fs34.existsSync)(path2)) continue;
13309
+ const text7 = (0, import_node_fs34.readFileSync)(path2, "utf8");
13252
13310
  if (/network_access\s*=\s*true/.test(text7)) return true;
13253
13311
  }
13254
13312
  return false;
@@ -13280,21 +13338,21 @@ function asRecord2(value) {
13280
13338
  return void 0;
13281
13339
  }
13282
13340
  function codexLooksAuthenticated() {
13283
- const authPath = (0, import_node_path35.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
13284
- if (!(0, import_node_fs33.existsSync)(authPath)) return false;
13341
+ const authPath = (0, import_node_path36.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
13342
+ if (!(0, import_node_fs34.existsSync)(authPath)) return false;
13285
13343
  try {
13286
- return (0, import_node_fs33.statSync)(authPath).size > 2;
13344
+ return (0, import_node_fs34.statSync)(authPath).size > 2;
13287
13345
  } catch {
13288
13346
  return false;
13289
13347
  }
13290
13348
  }
13291
- var import_node_fs33, import_node_os12, import_node_path35, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
13349
+ var import_node_fs34, import_node_os12, import_node_path36, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
13292
13350
  var init_codex = __esm({
13293
13351
  "src/agents/codex.ts"() {
13294
13352
  "use strict";
13295
- import_node_fs33 = require("fs");
13353
+ import_node_fs34 = require("fs");
13296
13354
  import_node_os12 = require("os");
13297
- import_node_path35 = require("path");
13355
+ import_node_path36 = require("path");
13298
13356
  init_run();
13299
13357
  init_app_settings();
13300
13358
  init_global_workspace();
@@ -13320,7 +13378,7 @@ var init_codex = __esm({
13320
13378
  async detect() {
13321
13379
  const codex = resolveAgentExecutable("codex");
13322
13380
  if (codex !== "codex") {
13323
- if (!(0, import_node_fs33.existsSync)(codex)) {
13381
+ if (!(0, import_node_fs34.existsSync)(codex)) {
13324
13382
  return {
13325
13383
  agent: "codex",
13326
13384
  installed: false,
@@ -13820,21 +13878,21 @@ function platformRipgrepPackage() {
13820
13878
  }
13821
13879
  function usableRipgrepPath(candidate) {
13822
13880
  const raw = candidate?.trim();
13823
- if (!raw || !(0, import_node_path36.isAbsolute)(raw)) return null;
13881
+ if (!raw || !(0, import_node_path37.isAbsolute)(raw)) return null;
13824
13882
  const readable = nodeReadableScriptPath(raw);
13825
- if (!(0, import_node_fs34.existsSync)(readable) || isAsarPath(readable)) return null;
13883
+ if (!(0, import_node_fs35.existsSync)(readable) || isAsarPath(readable)) return null;
13826
13884
  return readable;
13827
13885
  }
13828
13886
  function walkForBundledRipgrep(startFile) {
13829
13887
  if (!startFile) return null;
13830
13888
  const pkg = platformRipgrepPackage();
13831
13889
  const name = rgBinaryName();
13832
- let dir = (0, import_node_path36.dirname)((0, import_node_path36.resolve)(startFile));
13833
- const root = (0, import_node_path36.parse)(dir).root;
13890
+ let dir = (0, import_node_path37.dirname)((0, import_node_path37.resolve)(startFile));
13891
+ const root = (0, import_node_path37.parse)(dir).root;
13834
13892
  while (dir !== root) {
13835
- const hit = usableRipgrepPath((0, import_node_path36.join)(dir, "node_modules", pkg, "bin", name));
13893
+ const hit = usableRipgrepPath((0, import_node_path37.join)(dir, "node_modules", pkg, "bin", name));
13836
13894
  if (hit) return hit;
13837
- const next = (0, import_node_path36.dirname)(dir);
13895
+ const next = (0, import_node_path37.dirname)(dir);
13838
13896
  if (next === dir) break;
13839
13897
  dir = next;
13840
13898
  }
@@ -13844,7 +13902,7 @@ function requireResolveBundledRipgrep(fromFile) {
13844
13902
  try {
13845
13903
  const req = (0, import_node_module2.createRequire)(fromFile);
13846
13904
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
13847
- return usableRipgrepPath((0, import_node_path36.join)((0, import_node_path36.dirname)(pkgJson), "bin", rgBinaryName()));
13905
+ return usableRipgrepPath((0, import_node_path37.join)((0, import_node_path37.dirname)(pkgJson), "bin", rgBinaryName()));
13848
13906
  } catch {
13849
13907
  return null;
13850
13908
  }
@@ -13866,13 +13924,13 @@ function cursorRipgrepEnv(opts) {
13866
13924
  const path2 = resolveCursorRipgrepPath(opts);
13867
13925
  return path2 ? { [RIPGREP_ENV]: path2 } : {};
13868
13926
  }
13869
- var import_node_fs34, import_node_module2, import_node_path36, RIPGREP_ENV;
13927
+ var import_node_fs35, import_node_module2, import_node_path37, RIPGREP_ENV;
13870
13928
  var init_cursor_ripgrep = __esm({
13871
13929
  "src/agents/cursor-ripgrep.ts"() {
13872
13930
  "use strict";
13873
- import_node_fs34 = require("fs");
13931
+ import_node_fs35 = require("fs");
13874
13932
  import_node_module2 = require("module");
13875
- import_node_path36 = require("path");
13933
+ import_node_path37 = require("path");
13876
13934
  init_node_launch();
13877
13935
  init_packaged_runtime();
13878
13936
  RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
@@ -13921,11 +13979,11 @@ function entryDir() {
13921
13979
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
13922
13980
  if (cjsDir) return cjsDir;
13923
13981
  try {
13924
- return (0, import_node_path37.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
13982
+ return (0, import_node_path38.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
13925
13983
  } catch {
13926
13984
  try {
13927
13985
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
13928
- return (0, import_node_path37.dirname)(req.resolve("@sideboard-ai/core"));
13986
+ return (0, import_node_path38.dirname)(req.resolve("@sideboard-ai/core"));
13929
13987
  } catch {
13930
13988
  return process.cwd();
13931
13989
  }
@@ -13936,27 +13994,27 @@ function cursorRunnerPath() {
13936
13994
  if (packaged) return packaged;
13937
13995
  const root = entryDir();
13938
13996
  const candidates = [
13939
- (0, import_node_path37.join)(root, "agents", "cursor-runner.js"),
13940
- (0, import_node_path37.join)(root, "agents", "cursor-runner.cjs"),
13997
+ (0, import_node_path38.join)(root, "agents", "cursor-runner.js"),
13998
+ (0, import_node_path38.join)(root, "agents", "cursor-runner.cjs"),
13941
13999
  // If somehow resolved from package root instead of dist/
13942
- (0, import_node_path37.join)(root, "dist", "agents", "cursor-runner.js"),
13943
- (0, import_node_path37.join)(root, "dist", "agents", "cursor-runner.cjs"),
14000
+ (0, import_node_path38.join)(root, "dist", "agents", "cursor-runner.js"),
14001
+ (0, import_node_path38.join)(root, "dist", "agents", "cursor-runner.cjs"),
13944
14002
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
13945
- (0, import_node_path37.join)(root, "cursor-runner.ts"),
13946
- (0, import_node_path37.join)(root, "src", "agents", "cursor-runner.ts")
14003
+ (0, import_node_path38.join)(root, "cursor-runner.ts"),
14004
+ (0, import_node_path38.join)(root, "src", "agents", "cursor-runner.ts")
13947
14005
  ];
13948
14006
  for (const candidate of candidates) {
13949
- if ((0, import_node_fs35.existsSync)(candidate)) return candidate;
14007
+ if ((0, import_node_fs36.existsSync)(candidate)) return candidate;
13950
14008
  }
13951
14009
  return candidates[0];
13952
14010
  }
13953
- var import_node_fs35, import_node_module3, import_node_path37, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
14011
+ var import_node_fs36, import_node_module3, import_node_path38, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
13954
14012
  var init_cursor = __esm({
13955
14013
  "src/agents/cursor.ts"() {
13956
14014
  "use strict";
13957
- import_node_fs35 = require("fs");
14015
+ import_node_fs36 = require("fs");
13958
14016
  import_node_module3 = require("module");
13959
- import_node_path37 = require("path");
14017
+ import_node_path38 = require("path");
13960
14018
  import_node_url2 = require("url");
13961
14019
  import_sdk = require("@cursor/sdk");
13962
14020
  init_run();
@@ -14108,7 +14166,7 @@ async function listOpencodeModels() {
14108
14166
  if (opencode === "opencode") {
14109
14167
  const which = await run("which", ["opencode"], { reject: false });
14110
14168
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
14111
- } else if (!(0, import_node_fs36.existsSync)(opencode)) {
14169
+ } else if (!(0, import_node_fs37.existsSync)(opencode)) {
14112
14170
  return FALLBACK_OPENCODE_MODELS;
14113
14171
  }
14114
14172
  const listed = await run(opencode, ["models"], { reject: false });
@@ -14138,11 +14196,11 @@ function usageFromOpencode(tokens) {
14138
14196
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
14139
14197
  };
14140
14198
  }
14141
- var import_node_fs36, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
14199
+ var import_node_fs37, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
14142
14200
  var init_opencode = __esm({
14143
14201
  "src/agents/opencode.ts"() {
14144
14202
  "use strict";
14145
- import_node_fs36 = require("fs");
14203
+ import_node_fs37 = require("fs");
14146
14204
  init_run();
14147
14205
  init_app_settings();
14148
14206
  init_global_workspace();
@@ -14170,7 +14228,7 @@ var init_opencode = __esm({
14170
14228
  async detect() {
14171
14229
  const opencode = resolveAgentExecutable("opencode");
14172
14230
  if (opencode !== "opencode") {
14173
- if (!(0, import_node_fs36.existsSync)(opencode)) {
14231
+ if (!(0, import_node_fs37.existsSync)(opencode)) {
14174
14232
  return {
14175
14233
  agent: "opencode",
14176
14234
  installed: false,
@@ -14889,14 +14947,14 @@ function accessTokenFromCredentialsJson(raw) {
14889
14947
  }
14890
14948
  }
14891
14949
  function claudeCredentialsPath() {
14892
- const root = process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path38.join)((0, import_node_os13.homedir)(), ".claude");
14893
- return (0, import_node_path38.join)(root, ".credentials.json");
14950
+ const root = process.env.CLAUDE_CONFIG_DIR?.trim() || (0, import_node_path39.join)((0, import_node_os13.homedir)(), ".claude");
14951
+ return (0, import_node_path39.join)(root, ".credentials.json");
14894
14952
  }
14895
14953
  async function readFileAccessToken() {
14896
14954
  const path2 = claudeCredentialsPath();
14897
- if (!(0, import_node_fs37.existsSync)(path2)) return null;
14955
+ if (!(0, import_node_fs38.existsSync)(path2)) return null;
14898
14956
  try {
14899
- return accessTokenFromCredentialsJson((0, import_node_fs37.readFileSync)(path2, "utf8"));
14957
+ return accessTokenFromCredentialsJson((0, import_node_fs38.readFileSync)(path2, "utf8"));
14900
14958
  } catch {
14901
14959
  return null;
14902
14960
  }
@@ -15000,13 +15058,13 @@ async function getClaudePlanUsage(opts = {}) {
15000
15058
  })();
15001
15059
  return inflight;
15002
15060
  }
15003
- var import_node_fs37, import_node_os13, import_node_path38, CLAUDE_OAUTH_USAGE_URL, CLAUDE_USAGE_TTL_MS, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS, KEYCHAIN_SERVICES, cache, errorUntil, inflight, lastGood, claudeVersion;
15061
+ var import_node_fs38, import_node_os13, import_node_path39, CLAUDE_OAUTH_USAGE_URL, CLAUDE_USAGE_TTL_MS, CLAUDE_USAGE_ERROR_TTL_MS, CLAUDE_USAGE_STALE_OK_MS, KEYCHAIN_SERVICES, cache, errorUntil, inflight, lastGood, claudeVersion;
15004
15062
  var init_claude_usage_client = __esm({
15005
15063
  "src/agents/claude-usage-client.ts"() {
15006
15064
  "use strict";
15007
- import_node_fs37 = require("fs");
15065
+ import_node_fs38 = require("fs");
15008
15066
  import_node_os13 = require("os");
15009
- import_node_path38 = require("path");
15067
+ import_node_path39 = require("path");
15010
15068
  init_run();
15011
15069
  init_fetch();
15012
15070
  init_app_settings();
@@ -15367,17 +15425,79 @@ var init_agents = __esm({
15367
15425
  }
15368
15426
  });
15369
15427
 
15428
+ // src/hook/agent-host-env.ts
15429
+ function isAgentHostEnvKey(key) {
15430
+ if (DROP_EXACT.has(key)) return true;
15431
+ return DROP_PREFIXES.some((prefix) => key.startsWith(prefix));
15432
+ }
15433
+ function stripHostToolingPath(pathValue) {
15434
+ if (!pathValue?.trim()) return "";
15435
+ return pathValue.split(import_node_path40.delimiter).filter((part) => part && !HOST_PATH_NOISE.test(part.replace(/\\/g, "/"))).join(import_node_path40.delimiter);
15436
+ }
15437
+ function sanitizeAgentHostEnv(env, cwd) {
15438
+ for (const key of Object.keys(env)) {
15439
+ if (isAgentHostEnvKey(key)) delete env[key];
15440
+ }
15441
+ env.PATH = stripHostToolingPath(env.PATH);
15442
+ const worktree = cwd?.trim();
15443
+ if (worktree) {
15444
+ env.PWD = worktree;
15445
+ env.INIT_CWD = worktree;
15446
+ }
15447
+ return env;
15448
+ }
15449
+ var import_node_path40, DROP_EXACT, DROP_PREFIXES, HOST_PATH_NOISE;
15450
+ var init_agent_host_env = __esm({
15451
+ "src/hook/agent-host-env.ts"() {
15452
+ "use strict";
15453
+ import_node_path40 = require("path");
15454
+ DROP_EXACT = /* @__PURE__ */ new Set([
15455
+ "NODE_PATH",
15456
+ "NODE_ENV_ELECTRON_VITE",
15457
+ "INIT_CWD",
15458
+ "npm_command",
15459
+ "npm_execpath",
15460
+ "npm_node_execpath",
15461
+ "npm_lifecycle_event",
15462
+ "npm_lifecycle_script",
15463
+ "PNPM_SCRIPT_SRC_DIR",
15464
+ "PNPM_STORE_DIR",
15465
+ "PORT",
15466
+ "SIDEBOARD_ROOT_PATH",
15467
+ "SIDEBOARD_IS_LOCAL",
15468
+ "SIDEBOARD_WORKSPACE_PATH",
15469
+ "SIDEBOARD_WORKSPACE_NAME",
15470
+ "SIDEBOARD_PORT",
15471
+ "CONDUCTOR_ROOT_PATH",
15472
+ "CONDUCTOR_IS_LOCAL",
15473
+ "CONDUCTOR_WORKSPACE_PATH",
15474
+ "CONDUCTOR_WORKSPACE_NAME",
15475
+ "CONDUCTOR_PORT",
15476
+ "CONDUCTOR_DEFAULT_BRANCH",
15477
+ "SIDEBOARD_DEFAULT_BRANCH"
15478
+ ]);
15479
+ DROP_PREFIXES = [
15480
+ "npm_package_",
15481
+ "npm_config_",
15482
+ "PNPM_",
15483
+ "SIDEBOARD_PORT_",
15484
+ "CONDUCTOR_PORT_"
15485
+ ];
15486
+ HOST_PATH_NOISE = /(?:^|\/)node_modules\/\.bin(?:\/|$)|node-gyp-bin|electron-vite/i;
15487
+ }
15488
+ });
15489
+
15370
15490
  // src/hook/worktree-pkg-cache.ts
15371
15491
  function worktreePkgCacheRoot(worktreePath) {
15372
- return (0, import_node_path39.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
15492
+ return (0, import_node_path41.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
15373
15493
  }
15374
15494
  function worktreePkgCacheEnv(worktreePath) {
15375
15495
  const root = worktreePkgCacheRoot(worktreePath);
15376
- const store = (0, import_node_path39.join)(root, "pnpm-store");
15377
- const pnpmCache = (0, import_node_path39.join)(root, "pnpm");
15378
- const npmCache = (0, import_node_path39.join)(root, "npm");
15379
- const nodeGyp = (0, import_node_path39.join)(root, "node-gyp");
15380
- const electron = (0, import_node_path39.join)(root, "electron");
15496
+ const store = (0, import_node_path41.join)(root, "pnpm-store");
15497
+ const pnpmCache = (0, import_node_path41.join)(root, "pnpm");
15498
+ const npmCache = (0, import_node_path41.join)(root, "npm");
15499
+ const nodeGyp = (0, import_node_path41.join)(root, "node-gyp");
15500
+ const electron = (0, import_node_path41.join)(root, "electron");
15381
15501
  return {
15382
15502
  npm_config_store_dir: store,
15383
15503
  PNPM_STORE_DIR: store,
@@ -15399,8 +15519,8 @@ function fillGroup(env, keys, values) {
15399
15519
  }
15400
15520
  }
15401
15521
  function ensureWorktreePkgCacheDirs(worktreePath) {
15402
- if (!(0, import_node_fs38.existsSync)(worktreePath)) return;
15403
- (0, import_node_fs38.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
15522
+ if (!(0, import_node_fs39.existsSync)(worktreePath)) return;
15523
+ (0, import_node_fs39.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
15404
15524
  }
15405
15525
  function applyWorktreePkgCacheEnv(env, worktreePath) {
15406
15526
  const cwd = worktreePath.trim();
@@ -15413,12 +15533,12 @@ function applyWorktreePkgCacheEnv(env, worktreePath) {
15413
15533
  fillGroup(env, ["electron_config_cache"], next);
15414
15534
  ensureWorktreePkgCacheDirs(cwd);
15415
15535
  }
15416
- var import_node_fs38, import_node_path39, WORKTREE_PKG_CACHE_REL;
15536
+ var import_node_fs39, import_node_path41, WORKTREE_PKG_CACHE_REL;
15417
15537
  var init_worktree_pkg_cache = __esm({
15418
15538
  "src/hook/worktree-pkg-cache.ts"() {
15419
15539
  "use strict";
15420
- import_node_fs38 = require("fs");
15421
- import_node_path39 = require("path");
15540
+ import_node_fs39 = require("fs");
15541
+ import_node_path41 = require("path");
15422
15542
  WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
15423
15543
  }
15424
15544
  });
@@ -15516,26 +15636,54 @@ async function spawnAgentTurn(thread, input, onEvent) {
15516
15636
  assertOrchestratorCapableAgent(thread.agent);
15517
15637
  }
15518
15638
  const adapter = getAdapter(thread.agent);
15519
- const cmd = await adapter.buildTurn(thread, input);
15639
+ const orch = isOrchestratorThread(thread);
15640
+ traceTurn("spawn.buildTurn.start", {
15641
+ threadId: thread.id,
15642
+ agent: thread.agent,
15643
+ orch,
15644
+ cwd: thread.worktreePath
15645
+ });
15646
+ const cmd = await withTimeout(
15647
+ adapter.buildTurn(thread, input),
15648
+ 2e4,
15649
+ "buildTurn"
15650
+ );
15651
+ traceTurn("spawn.buildTurn.done", { file: cmd.file, cwd: cmd.cwd });
15520
15652
  if (cmd.cwd !== thread.worktreePath) {
15521
15653
  throw new Error(
15522
15654
  `Agent cwd must be the thread worktree (got ${cmd.cwd}, expected ${thread.worktreePath})`
15523
15655
  );
15524
15656
  }
15525
15657
  const env = childEnvWithAppSettings(cmd.env);
15658
+ sanitizeAgentHostEnv(env, cmd.cwd);
15659
+ ensureAgentPath(env);
15526
15660
  applyPromptCacheTtlEnv(thread.agent, env);
15527
15661
  applyAgentRunnerHeapEnv(env);
15528
- if (!isOrchestratorThread(thread)) {
15662
+ if (!orch) {
15529
15663
  applyWorktreePkgCacheEnv(env, thread.worktreePath);
15530
15664
  }
15531
15665
  try {
15532
- if (isOrchestratorThread(thread)) {
15533
- mergeAgentGitAuthEnv(env, await resolveAgentGitAuthEnv(env));
15534
- } else {
15535
- mergeAgentGitAuthEnv(env, await originGhRepoEnv(thread.worktreePath, { env }));
15666
+ traceTurn("spawn.gitAuth.start");
15667
+ mergeAgentGitAuthEnv(
15668
+ env,
15669
+ await withTimeout(
15670
+ resolveAgentGitAuthEnv(env, { cwd: thread.worktreePath }),
15671
+ 8e3,
15672
+ "gitAuth"
15673
+ )
15674
+ );
15675
+ if (!orch) {
15676
+ const slug = await withTimeout(
15677
+ resolveGithubRepoSlug(thread.worktreePath),
15678
+ 8e3,
15679
+ "resolveGithubRepoSlug"
15680
+ );
15681
+ if (slug) env.GH_REPO = slug;
15536
15682
  }
15683
+ traceTurn("spawn.gitAuth.done", { ghRepo: env.GH_REPO ?? null });
15537
15684
  } catch (err) {
15538
15685
  const detail = err instanceof Error ? err.message : String(err);
15686
+ traceTurn("spawn.gitAuth.fail", { detail });
15539
15687
  console.warn(`[sideboard] git auth env failed (${thread.worktreePath}): ${detail}`);
15540
15688
  }
15541
15689
  const child = (0, import_execa3.execa)(cmd.file, cmd.args, {
@@ -15548,6 +15696,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
15548
15696
  // so Claude doesn't wait ~3s for an empty pipe.
15549
15697
  stdin: cmd.stdin != null ? "pipe" : "ignore"
15550
15698
  });
15699
+ traceTurn("spawn.execa", { pid: child.pid ?? null, file: cmd.file });
15551
15700
  if (cmd.stdin != null && child.stdin) {
15552
15701
  child.stdin.write(cmd.stdin);
15553
15702
  child.stdin.end();
@@ -15631,10 +15780,12 @@ var init_spawn = __esm({
15631
15780
  init_git_auth_mode();
15632
15781
  init_app_settings();
15633
15782
  init_global_workspace();
15783
+ init_turn_trace();
15634
15784
  init_brightsy();
15635
15785
  init_agents();
15636
15786
  init_orchestrator_capable();
15637
15787
  init_message_parts();
15788
+ init_agent_host_env();
15638
15789
  init_worktree_pkg_cache();
15639
15790
  init_node_launch();
15640
15791
  init_path();
@@ -16622,21 +16773,21 @@ function shouldRefreshReviewRequestTemplate(content) {
16622
16773
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
16623
16774
  }
16624
16775
  function readTextIfPresent(abs) {
16625
- if (!(0, import_node_fs39.existsSync)(abs)) return null;
16776
+ if (!(0, import_node_fs40.existsSync)(abs)) return null;
16626
16777
  try {
16627
- const content = (0, import_node_fs39.readFileSync)(abs, "utf8");
16778
+ const content = (0, import_node_fs40.readFileSync)(abs, "utf8");
16628
16779
  return content.trim() ? content : null;
16629
16780
  } catch {
16630
16781
  return null;
16631
16782
  }
16632
16783
  }
16633
16784
  function readLocalGuidelines(worktreePath) {
16634
- const localAbs = (0, import_node_path40.join)(worktreePath, REVIEW_REQUEST_PATH);
16785
+ const localAbs = (0, import_node_path42.join)(worktreePath, REVIEW_REQUEST_PATH);
16635
16786
  const localContent = readTextIfPresent(localAbs);
16636
16787
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
16637
16788
  return { path: REVIEW_REQUEST_PATH, content: localContent };
16638
16789
  }
16639
- const legacyAbs = (0, import_node_path40.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
16790
+ const legacyAbs = (0, import_node_path42.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
16640
16791
  const legacyContent = readTextIfPresent(legacyAbs);
16641
16792
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
16642
16793
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -16660,27 +16811,27 @@ function contextGuidelines(content, source) {
16660
16811
  };
16661
16812
  }
16662
16813
  function writeContextGuidelines(worktreePath, content) {
16663
- const abs = (0, import_node_path40.join)(worktreePath, CONTEXT_REVIEW_PATH);
16664
- (0, import_node_fs39.mkdirSync)((0, import_node_path40.dirname)(abs), { recursive: true });
16814
+ const abs = (0, import_node_path42.join)(worktreePath, CONTEXT_REVIEW_PATH);
16815
+ (0, import_node_fs40.mkdirSync)((0, import_node_path42.dirname)(abs), { recursive: true });
16665
16816
  const body = content.endsWith("\n") ? content : `${content}
16666
16817
  `;
16667
- (0, import_node_fs39.writeFileSync)(abs, body, "utf8");
16818
+ (0, import_node_fs40.writeFileSync)(abs, body, "utf8");
16668
16819
  return body;
16669
16820
  }
16670
16821
  function readSideboardReview(worktreePath, repoPath) {
16671
- const fromWorktree = readTextIfPresent((0, import_node_path40.join)(worktreePath, REPO_REVIEW_PATH));
16822
+ const fromWorktree = readTextIfPresent((0, import_node_path42.join)(worktreePath, REPO_REVIEW_PATH));
16672
16823
  if (fromWorktree) return fromWorktree;
16673
16824
  const repo = repoPath?.replace(/\/+$/, "");
16674
16825
  const wt = worktreePath.replace(/\/+$/, "");
16675
16826
  if (!repo || repo === wt) return null;
16676
- return readTextIfPresent((0, import_node_path40.join)(repo, REPO_REVIEW_PATH));
16827
+ return readTextIfPresent((0, import_node_path42.join)(repo, REPO_REVIEW_PATH));
16677
16828
  }
16678
16829
  function ensureReviewGuidelinesFile(worktreePath, repoPath) {
16679
- const skillContent = readTextIfPresent((0, import_node_path40.join)(worktreePath, REVIEW_SKILL_PATH));
16830
+ const skillContent = readTextIfPresent((0, import_node_path42.join)(worktreePath, REVIEW_SKILL_PATH));
16680
16831
  if (skillContent) {
16681
16832
  return { ...skillGuidelines(skillContent, "skill"), wrote: false };
16682
16833
  }
16683
- const contextContent = readTextIfPresent((0, import_node_path40.join)(worktreePath, CONTEXT_REVIEW_PATH));
16834
+ const contextContent = readTextIfPresent((0, import_node_path42.join)(worktreePath, CONTEXT_REVIEW_PATH));
16684
16835
  if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
16685
16836
  return { ...contextGuidelines(contextContent, "local"), wrote: false };
16686
16837
  }
@@ -16718,7 +16869,7 @@ function buildReviewRequestAttachment(content, opts) {
16718
16869
  };
16719
16870
  }
16720
16871
  function readExistingReviewRequestFile(worktreePath) {
16721
- return readTextIfPresent((0, import_node_path40.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path40.join)(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path40.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path40.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path40.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
16872
+ return readTextIfPresent((0, import_node_path42.join)(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path42.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
16722
16873
  }
16723
16874
  async function requestReview(threadRef, send2) {
16724
16875
  const from = findThreadByRef(threadRef);
@@ -16745,13 +16896,13 @@ async function requestReview(threadRef, send2) {
16745
16896
  const started = await send2(tab.id, REVIEW_REQUEST_PREFILL);
16746
16897
  return { tab: started, from };
16747
16898
  }
16748
- var import_node_crypto9, import_node_fs39, import_node_path40, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
16899
+ var import_node_crypto9, import_node_fs40, import_node_path42, REPO_REVIEW_PATH, REPO_REVIEW_NAME, CONTEXT_REVIEW_PATH, REVIEW_REQUEST_PATH, LEGACY_REVIEW_REQUEST_PATH, REVIEW_REQUEST_NAME, REVIEW_REQUEST_PREFILL, LEGACY_REVIEW_TEMPLATE_MARKERS;
16749
16900
  var init_request_review = __esm({
16750
16901
  "src/review/request-review.ts"() {
16751
16902
  "use strict";
16752
16903
  import_node_crypto9 = require("crypto");
16753
- import_node_fs39 = require("fs");
16754
- import_node_path40 = require("path");
16904
+ import_node_fs40 = require("fs");
16905
+ import_node_path42 = require("path");
16755
16906
  init_global_workspace();
16756
16907
  init_chat_tabs();
16757
16908
  init_thread_store();
@@ -16777,9 +16928,9 @@ function matchSimpleGlob(pattern, name) {
16777
16928
  return new RegExp(`^${escaped}$`).test(name);
16778
16929
  }
16779
16930
  function readWorktreeInclude(repoPath) {
16780
- const path2 = (0, import_node_path41.join)(repoPath, ".worktreeinclude");
16781
- if (!(0, import_node_fs40.existsSync)(path2)) return [];
16782
- return (0, import_node_fs40.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
16931
+ const path2 = (0, import_node_path43.join)(repoPath, ".worktreeinclude");
16932
+ if (!(0, import_node_fs41.existsSync)(path2)) return [];
16933
+ return (0, import_node_fs41.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
16783
16934
  }
16784
16935
  function resolveFilesToCopy(repoPath) {
16785
16936
  const fromInclude = readWorktreeInclude(repoPath);
@@ -16789,10 +16940,10 @@ function resolveFilesToCopy(repoPath) {
16789
16940
  if (settings?.fileIncludeGlobs?.length) {
16790
16941
  const matched = [];
16791
16942
  try {
16792
- for (const entry of (0, import_node_fs40.readdirSync)(repoPath, { withFileTypes: true })) {
16943
+ for (const entry of (0, import_node_fs41.readdirSync)(repoPath, { withFileTypes: true })) {
16793
16944
  if (!entry.isFile()) continue;
16794
16945
  for (const glob of settings.fileIncludeGlobs) {
16795
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path41.basename)(glob), entry.name)) {
16946
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path43.basename)(glob), entry.name)) {
16796
16947
  matched.push(entry.name);
16797
16948
  break;
16798
16949
  }
@@ -16804,7 +16955,7 @@ function resolveFilesToCopy(repoPath) {
16804
16955
  }
16805
16956
  const defaults = [];
16806
16957
  try {
16807
- for (const entry of (0, import_node_fs40.readdirSync)(repoPath, { withFileTypes: true })) {
16958
+ for (const entry of (0, import_node_fs41.readdirSync)(repoPath, { withFileTypes: true })) {
16808
16959
  if (entry.isFile() && entry.name.startsWith(".env")) {
16809
16960
  defaults.push(entry.name);
16810
16961
  }
@@ -16818,11 +16969,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
16818
16969
  const patterns = resolveFilesToCopy(repoPath);
16819
16970
  const copied = [];
16820
16971
  for (const rel of patterns) {
16821
- const src = (0, import_node_path41.join)(repoPath, rel);
16822
- if (!(0, import_node_fs40.existsSync)(src)) continue;
16823
- const dest = (0, import_node_path41.join)(worktreePath, rel);
16824
- (0, import_node_fs40.mkdirSync)((0, import_node_path41.dirname)(dest), { recursive: true });
16825
- (0, import_node_fs40.copyFileSync)(src, dest);
16972
+ const src = (0, import_node_path43.join)(repoPath, rel);
16973
+ if (!(0, import_node_fs41.existsSync)(src)) continue;
16974
+ const dest = (0, import_node_path43.join)(worktreePath, rel);
16975
+ (0, import_node_fs41.mkdirSync)((0, import_node_path43.dirname)(dest), { recursive: true });
16976
+ (0, import_node_fs41.copyFileSync)(src, dest);
16826
16977
  copied.push(rel);
16827
16978
  }
16828
16979
  return copied;
@@ -16857,7 +17008,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
16857
17008
  const env = stripNestedElectronEnv({
16858
17009
  ...baseEnv ?? process.env
16859
17010
  });
16860
- const name = opts.workspaceName ?? (0, import_node_path41.basename)(opts.worktreePath);
17011
+ const name = opts.workspaceName ?? (0, import_node_path43.basename)(opts.worktreePath);
16861
17012
  const ports = opts.ports ?? [];
16862
17013
  const primary = ports[0];
16863
17014
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -17120,13 +17271,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
17120
17271
  done: handle.done
17121
17272
  };
17122
17273
  }
17123
- var import_node_fs40, import_node_net, import_node_path41, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
17274
+ var import_node_fs41, import_node_net, import_node_path43, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
17124
17275
  var init_conductor = __esm({
17125
17276
  "src/hook/conductor.ts"() {
17126
17277
  "use strict";
17127
- import_node_fs40 = require("fs");
17278
+ import_node_fs41 = require("fs");
17128
17279
  import_node_net = require("net");
17129
- import_node_path41 = require("path");
17280
+ import_node_path43 = require("path");
17130
17281
  import_execa4 = require("execa");
17131
17282
  import_node_readline3 = require("readline");
17132
17283
  init_settings();
@@ -17154,9 +17305,9 @@ async function findOrphanWorktrees(repoPaths) {
17154
17305
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
17155
17306
  );
17156
17307
  const homeRoot = sideboardWorkspacesDir();
17157
- if ((0, import_node_fs41.existsSync)(homeRoot)) {
17308
+ if ((0, import_node_fs42.existsSync)(homeRoot)) {
17158
17309
  try {
17159
- for (const entry of (0, import_node_fs41.readdirSync)(homeRoot, { withFileTypes: true })) {
17310
+ for (const entry of (0, import_node_fs42.readdirSync)(homeRoot, { withFileTypes: true })) {
17160
17311
  if (!entry.isDirectory()) continue;
17161
17312
  void entry;
17162
17313
  }
@@ -17166,7 +17317,7 @@ async function findOrphanWorktrees(repoPaths) {
17166
17317
  const orphans = [];
17167
17318
  const seen = /* @__PURE__ */ new Set();
17168
17319
  for (const repoPath of repos) {
17169
- if (!repoPath || !(0, import_node_fs41.existsSync)(repoPath)) continue;
17320
+ if (!repoPath || !(0, import_node_fs42.existsSync)(repoPath)) continue;
17170
17321
  try {
17171
17322
  const wts = await listWorktrees(repoPath);
17172
17323
  for (const wt of wts) {
@@ -17177,7 +17328,7 @@ async function findOrphanWorktrees(repoPaths) {
17177
17328
  seen.add(path2);
17178
17329
  let mtimeMs = 0;
17179
17330
  try {
17180
- mtimeMs = (0, import_node_fs41.statSync)(path2).mtimeMs;
17331
+ mtimeMs = (0, import_node_fs42.statSync)(path2).mtimeMs;
17181
17332
  } catch {
17182
17333
  mtimeMs = 0;
17183
17334
  }
@@ -17187,16 +17338,16 @@ async function findOrphanWorktrees(repoPaths) {
17187
17338
  }
17188
17339
  try {
17189
17340
  const root = worktreesRoot(repoPath);
17190
- if ((0, import_node_fs41.existsSync)(root)) {
17191
- for (const entry of (0, import_node_fs41.readdirSync)(root, { withFileTypes: true })) {
17341
+ if ((0, import_node_fs42.existsSync)(root)) {
17342
+ for (const entry of (0, import_node_fs42.readdirSync)(root, { withFileTypes: true })) {
17192
17343
  if (!entry.isDirectory()) continue;
17193
- const path2 = (0, import_node_path42.join)(root, entry.name).replace(/\/$/, "");
17344
+ const path2 = (0, import_node_path44.join)(root, entry.name).replace(/\/$/, "");
17194
17345
  if (known.has(path2) || seen.has(path2)) continue;
17195
- if (!(0, import_node_fs41.existsSync)((0, import_node_path42.join)(path2, ".git"))) continue;
17346
+ if (!(0, import_node_fs42.existsSync)((0, import_node_path44.join)(path2, ".git"))) continue;
17196
17347
  seen.add(path2);
17197
17348
  let mtimeMs = 0;
17198
17349
  try {
17199
- mtimeMs = (0, import_node_fs41.statSync)(path2).mtimeMs;
17350
+ mtimeMs = (0, import_node_fs42.statSync)(path2).mtimeMs;
17200
17351
  } catch {
17201
17352
  mtimeMs = Date.now();
17202
17353
  }
@@ -17257,12 +17408,12 @@ function worktreeCleanupSettings() {
17257
17408
  autoCleanupOrphans: a.autoCleanupOrphans
17258
17409
  };
17259
17410
  }
17260
- var import_node_fs41, import_node_path42;
17411
+ var import_node_fs42, import_node_path44;
17261
17412
  var init_orphan_cleanup = __esm({
17262
17413
  "src/git/orphan-cleanup.ts"() {
17263
17414
  "use strict";
17264
- import_node_fs41 = require("fs");
17265
- import_node_path42 = require("path");
17415
+ import_node_fs42 = require("fs");
17416
+ import_node_path44 = require("path");
17266
17417
  init_worktree();
17267
17418
  init_thread_store();
17268
17419
  init_paths();
@@ -17437,12 +17588,12 @@ async function cloneRepoIntoSideboard(opts) {
17437
17588
  if (!url) throw new Error("Clone URL is required");
17438
17589
  let name = opts.name?.trim();
17439
17590
  if (!name) {
17440
- const leaf = (0, import_node_path43.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
17591
+ const leaf = (0, import_node_path45.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
17441
17592
  name = leaf || "repo";
17442
17593
  }
17443
17594
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
17444
- const dest = (0, import_node_path43.join)(sideboardReposDir(), name);
17445
- if ((0, import_node_fs42.existsSync)(dest)) {
17595
+ const dest = (0, import_node_path45.join)(sideboardReposDir(), name);
17596
+ if ((0, import_node_fs43.existsSync)(dest)) {
17446
17597
  const repoPath2 = await resolveRepoRoot(dest);
17447
17598
  const workspace2 = await ensureWorkspace(repoPath2);
17448
17599
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -17457,12 +17608,12 @@ async function cloneRepoIntoSideboard(opts) {
17457
17608
  const workspace = await ensureWorkspace(repoPath);
17458
17609
  return { repoPath, workspace };
17459
17610
  }
17460
- var import_node_fs42, import_node_path43, import_execa6;
17611
+ var import_node_fs43, import_node_path45, import_execa6;
17461
17612
  var init_clone_repo = __esm({
17462
17613
  "src/git/clone-repo.ts"() {
17463
17614
  "use strict";
17464
- import_node_fs42 = require("fs");
17465
- import_node_path43 = require("path");
17615
+ import_node_fs43 = require("fs");
17616
+ import_node_path45 = require("path");
17466
17617
  import_execa6 = require("execa");
17467
17618
  init_paths();
17468
17619
  init_workspaces();
@@ -17583,24 +17734,24 @@ function jobTreeAlive(pid) {
17583
17734
  return jobAlive(pid) || processGroupAlive(pid);
17584
17735
  }
17585
17736
  function readIntFile(file) {
17586
- if (!(0, import_node_fs43.existsSync)(file)) return null;
17587
- const n = Number.parseInt((0, import_node_fs43.readFileSync)(file, "utf8").trim(), 10);
17737
+ if (!(0, import_node_fs44.existsSync)(file)) return null;
17738
+ const n = Number.parseInt((0, import_node_fs44.readFileSync)(file, "utf8").trim(), 10);
17588
17739
  return Number.isInteger(n) ? n : null;
17589
17740
  }
17590
17741
  function jobDir(root, id, legacy = false) {
17591
- return (0, import_node_path44.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
17742
+ return (0, import_node_path46.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
17592
17743
  }
17593
17744
  function resolveJobDir(root, id) {
17594
17745
  const modern = jobDir(root, id, false);
17595
- if ((0, import_node_fs43.existsSync)(modern)) return modern;
17746
+ if ((0, import_node_fs44.existsSync)(modern)) return modern;
17596
17747
  const legacy = jobDir(root, id, true);
17597
- if ((0, import_node_fs43.existsSync)(legacy)) return legacy;
17748
+ if ((0, import_node_fs44.existsSync)(legacy)) return legacy;
17598
17749
  return modern;
17599
17750
  }
17600
17751
  function listJobIdsIn(root, rel) {
17601
- const dir = (0, import_node_path44.join)(root, rel);
17602
- if (!(0, import_node_fs43.existsSync)(dir)) return [];
17603
- return (0, import_node_fs43.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
17752
+ const dir = (0, import_node_path46.join)(root, rel);
17753
+ if (!(0, import_node_fs44.existsSync)(dir)) return [];
17754
+ return (0, import_node_fs44.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
17604
17755
  }
17605
17756
  function listRunningDetachedJobs(worktreePath) {
17606
17757
  const root = worktreePath.trim();
@@ -17612,7 +17763,7 @@ function listRunningDetachedJobs(worktreePath) {
17612
17763
  const running = [];
17613
17764
  for (const id of ids) {
17614
17765
  const dir = resolveJobDir(root, id);
17615
- const pid = readIntFile((0, import_node_path44.join)(dir, "pid"));
17766
+ const pid = readIntFile((0, import_node_path46.join)(dir, "pid"));
17616
17767
  if (jobTreeAlive(pid)) running.push(id);
17617
17768
  }
17618
17769
  return running.sort();
@@ -17625,6 +17776,7 @@ function looksLikeDeferredDonePromise(text7) {
17625
17776
  return /\b(i['’]?ll|i will)\s+let you know\b/i.test(unquoted) || /\blet you know when\b/i.test(unquoted) || /\b(check back|ping me)\s+when\b/i.test(unquoted) || /\bi(?:['’]ll| will)\s+(report|update you)\s+when\b/i.test(unquoted);
17626
17777
  }
17627
17778
  function isJobContinuePrompt(text7) {
17779
+ if (typeof text7 !== "string") return false;
17628
17780
  const t = text7.trim();
17629
17781
  return t.startsWith("Detached job still running:") || t.startsWith("You ended the turn after promising to report later");
17630
17782
  }
@@ -17694,8 +17846,8 @@ function planJobContinue(opts) {
17694
17846
  return { action: "none" };
17695
17847
  }
17696
17848
  function tailProgress(logFile, maxLines = 12) {
17697
- if (!(0, import_node_fs43.existsSync)(logFile)) return "(no log yet)";
17698
- const lines = (0, import_node_fs43.readFileSync)(logFile, "utf8").split("\n");
17849
+ if (!(0, import_node_fs44.existsSync)(logFile)) return "(no log yet)";
17850
+ const lines = (0, import_node_fs44.readFileSync)(logFile, "utf8").split("\n");
17699
17851
  return lines.slice(-maxLines).join("\n");
17700
17852
  }
17701
17853
  function lastProgressLine(progress) {
@@ -17703,8 +17855,8 @@ function lastProgressLine(progress) {
17703
17855
  return last ? last.slice(0, 72) : void 0;
17704
17856
  }
17705
17857
  function readLogLines(file) {
17706
- if (!(0, import_node_fs43.existsSync)(file)) return [];
17707
- const lines = (0, import_node_fs43.readFileSync)(file, "utf8").split("\n");
17858
+ if (!(0, import_node_fs44.existsSync)(file)) return [];
17859
+ const lines = (0, import_node_fs44.readFileSync)(file, "utf8").split("\n");
17708
17860
  if (lines.length && lines[lines.length - 1] === "") lines.pop();
17709
17861
  return lines;
17710
17862
  }
@@ -17715,15 +17867,15 @@ function takeDelta(logFile, cursorFile) {
17715
17867
  return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
17716
17868
  }
17717
17869
  function snapshotJob(dir) {
17718
- const pid = readIntFile((0, import_node_path44.join)(dir, "pid"));
17870
+ const pid = readIntFile((0, import_node_path46.join)(dir, "pid"));
17719
17871
  const running = jobTreeAlive(pid);
17720
17872
  return {
17721
17873
  pid,
17722
17874
  running,
17723
- exitCode: readIntFile((0, import_node_path44.join)(dir, "exit")),
17724
- log: (0, import_node_path44.join)(dir, "log"),
17725
- cursor: (0, import_node_path44.join)(dir, "present.cursor"),
17726
- progress: tailProgress((0, import_node_path44.join)(dir, "log"))
17875
+ exitCode: readIntFile((0, import_node_path46.join)(dir, "exit")),
17876
+ log: (0, import_node_path46.join)(dir, "log"),
17877
+ cursor: (0, import_node_path46.join)(dir, "present.cursor"),
17878
+ progress: tailProgress((0, import_node_path46.join)(dir, "log"))
17727
17879
  };
17728
17880
  }
17729
17881
  function toResult(id, snap, extra) {
@@ -17732,8 +17884,8 @@ function toResult(id, snap, extra) {
17732
17884
  const stillRunning = snap.running && !ok;
17733
17885
  const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
17734
17886
  try {
17735
- (0, import_node_fs43.mkdirSync)((0, import_node_path44.dirname)(snap.cursor), { recursive: true });
17736
- (0, import_node_fs43.writeFileSync)(snap.cursor, `${nextCursor}
17887
+ (0, import_node_fs44.mkdirSync)((0, import_node_path46.dirname)(snap.cursor), { recursive: true });
17888
+ (0, import_node_fs44.writeFileSync)(snap.cursor, `${nextCursor}
17737
17889
  `);
17738
17890
  } catch {
17739
17891
  }
@@ -17762,7 +17914,7 @@ async function waitForDetachedJob(cwd, id, opts) {
17762
17914
  const dir = resolveJobDir(root, jobId);
17763
17915
  const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
17764
17916
  const sleep2 = opts?.sleep ?? sleepMs;
17765
- if (!(0, import_node_fs43.existsSync)(dir)) {
17917
+ if (!(0, import_node_fs44.existsSync)(dir)) {
17766
17918
  return {
17767
17919
  stillRunning: false,
17768
17920
  ok: false,
@@ -17808,10 +17960,10 @@ function killProcessTree(pid, signal) {
17808
17960
  }
17809
17961
  function appendJobLog(logFile, line) {
17810
17962
  try {
17811
- (0, import_node_fs43.mkdirSync)((0, import_node_path44.dirname)(logFile), { recursive: true });
17963
+ (0, import_node_fs44.mkdirSync)((0, import_node_path46.dirname)(logFile), { recursive: true });
17812
17964
  const body = line.endsWith("\n") ? line : `${line}
17813
17965
  `;
17814
- (0, import_node_fs43.appendFileSync)(logFile, body);
17966
+ (0, import_node_fs44.appendFileSync)(logFile, body);
17815
17967
  } catch {
17816
17968
  }
17817
17969
  }
@@ -17821,7 +17973,7 @@ async function stopDetachedJob(cwd, id, opts) {
17821
17973
  const dir = resolveJobDir(root, jobId);
17822
17974
  const sleep2 = opts?.sleep ?? sleepMs;
17823
17975
  const why = opts?.reason?.trim() ?? "";
17824
- if (!(0, import_node_fs43.existsSync)(dir)) {
17976
+ if (!(0, import_node_fs44.existsSync)(dir)) {
17825
17977
  return {
17826
17978
  stillRunning: false,
17827
17979
  ok: false,
@@ -17857,10 +18009,10 @@ async function stopDetachedJob(cwd, id, opts) {
17857
18009
  killProcessTree(targetPid, "SIGKILL");
17858
18010
  await sleep2(100);
17859
18011
  }
17860
- const exitFile = (0, import_node_path44.join)(dir, "exit");
17861
- if (!(0, import_node_fs43.existsSync)(exitFile)) {
18012
+ const exitFile = (0, import_node_path46.join)(dir, "exit");
18013
+ if (!(0, import_node_fs44.existsSync)(exitFile)) {
17862
18014
  try {
17863
- (0, import_node_fs43.writeFileSync)(exitFile, "1\n");
18015
+ (0, import_node_fs44.writeFileSync)(exitFile, "1\n");
17864
18016
  } catch {
17865
18017
  }
17866
18018
  }
@@ -17880,12 +18032,12 @@ async function stopDetachedJob(cwd, id, opts) {
17880
18032
  hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
17881
18033
  };
17882
18034
  }
17883
- var import_node_fs43, import_node_path44, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
18035
+ var import_node_fs44, import_node_path46, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
17884
18036
  var init_wait_for_job = __esm({
17885
18037
  "src/mcp/wait-for-job.ts"() {
17886
18038
  "use strict";
17887
- import_node_fs43 = require("fs");
17888
- import_node_path44 = require("path");
18039
+ import_node_fs44 = require("fs");
18040
+ import_node_path46 = require("path");
17889
18041
  init_workspace_scratch();
17890
18042
  init_wait_for_turn();
17891
18043
  MAX_JOB_CONTINUES = 8;
@@ -19430,7 +19582,7 @@ function reuseLiveThread(input, repoPath, match) {
19430
19582
  }
19431
19583
  async function createThread(input, _onSetupLine) {
19432
19584
  const repoPath = await resolveRepoRoot(input.repoPath);
19433
- if (!(0, import_node_fs44.existsSync)(repoPath)) {
19585
+ if (!(0, import_node_fs45.existsSync)(repoPath)) {
19434
19586
  throw new Error(`Repo not found: ${repoPath}`);
19435
19587
  }
19436
19588
  const reused = reuseLiveThread(input, repoPath, {
@@ -19615,11 +19767,11 @@ async function listLinearIssues(agent, repoPath) {
19615
19767
  }
19616
19768
  return adapter.listLinearIssues(repoPath);
19617
19769
  }
19618
- var import_node_fs44;
19770
+ var import_node_fs45;
19619
19771
  var init_create = __esm({
19620
19772
  "src/threads/create.ts"() {
19621
19773
  "use strict";
19622
- import_node_fs44 = require("fs");
19774
+ import_node_fs45 = require("fs");
19623
19775
  init_detect();
19624
19776
  init_worktree();
19625
19777
  init_home_board();
@@ -19771,20 +19923,20 @@ function writeTurnLive(threadId, progress) {
19771
19923
  const path2 = threadLivePath(threadId);
19772
19924
  const tmp = `${path2}.${process.pid}.tmp`;
19773
19925
  try {
19774
- (0, import_node_fs45.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
19775
- (0, import_node_fs45.renameSync)(tmp, path2);
19926
+ (0, import_node_fs46.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
19927
+ (0, import_node_fs46.renameSync)(tmp, path2);
19776
19928
  } catch {
19777
19929
  try {
19778
- (0, import_node_fs45.unlinkSync)(tmp);
19930
+ (0, import_node_fs46.unlinkSync)(tmp);
19779
19931
  } catch {
19780
19932
  }
19781
19933
  }
19782
19934
  }
19783
19935
  function readTurnLive(threadId) {
19784
19936
  const path2 = threadLivePath(threadId);
19785
- if (!(0, import_node_fs45.existsSync)(path2)) return null;
19937
+ if (!(0, import_node_fs46.existsSync)(path2)) return null;
19786
19938
  try {
19787
- const raw = JSON.parse((0, import_node_fs45.readFileSync)(path2, "utf8"));
19939
+ const raw = JSON.parse((0, import_node_fs46.readFileSync)(path2, "utf8"));
19788
19940
  if (!raw || typeof raw.summary !== "string") return null;
19789
19941
  return raw;
19790
19942
  } catch {
@@ -19796,17 +19948,17 @@ function clearTurnLive(threadId) {
19796
19948
  if (buf?.timer) clearTimeout(buf.timer);
19797
19949
  buffers.delete(threadId);
19798
19950
  const path2 = threadLivePath(threadId);
19799
- if (!(0, import_node_fs45.existsSync)(path2)) return;
19951
+ if (!(0, import_node_fs46.existsSync)(path2)) return;
19800
19952
  try {
19801
- (0, import_node_fs45.unlinkSync)(path2);
19953
+ (0, import_node_fs46.unlinkSync)(path2);
19802
19954
  } catch {
19803
19955
  }
19804
19956
  }
19805
- var import_node_fs45, buffers, FLUSH_MS, MAX_PARTS;
19957
+ var import_node_fs46, buffers, FLUSH_MS, MAX_PARTS;
19806
19958
  var init_turn_live = __esm({
19807
19959
  "src/store/turn-live.ts"() {
19808
19960
  "use strict";
19809
- import_node_fs45 = require("fs");
19961
+ import_node_fs46 = require("fs");
19810
19962
  init_message_parts();
19811
19963
  init_paths();
19812
19964
  buffers = /* @__PURE__ */ new Map();
@@ -20050,7 +20202,7 @@ var init_quota_failover = __esm({
20050
20202
  // src/threads/adopt.ts
20051
20203
  function thisModuleFile() {
20052
20204
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
20053
- return cjsFile || process.argv[1] || (0, import_node_path45.join)(process.cwd(), "package.json");
20205
+ return cjsFile || process.argv[1] || (0, import_node_path47.join)(process.cwd(), "package.json");
20054
20206
  }
20055
20207
  function openReadonlySqlite(file) {
20056
20208
  const req = (0, import_node_module4.createRequire)(thisModuleFile());
@@ -20068,21 +20220,21 @@ function mapAgentType(raw) {
20068
20220
  return null;
20069
20221
  }
20070
20222
  function resolveConductorCursorAgentId(workspacePath) {
20071
- if (!workspacePath || !(0, import_node_fs46.existsSync)(CURSOR_SDK_STORE)) return null;
20223
+ if (!workspacePath || !(0, import_node_fs47.existsSync)(CURSOR_SDK_STORE)) return null;
20072
20224
  const normalized = workspacePath.replace(/\/$/, "");
20073
20225
  let best = null;
20074
20226
  let hashes;
20075
20227
  try {
20076
- hashes = (0, import_node_fs46.readdirSync)(CURSOR_SDK_STORE);
20228
+ hashes = (0, import_node_fs47.readdirSync)(CURSOR_SDK_STORE);
20077
20229
  } catch {
20078
20230
  return null;
20079
20231
  }
20080
20232
  for (const hash of hashes) {
20081
- const agentsFile = (0, import_node_path45.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
20082
- if (!(0, import_node_fs46.existsSync)(agentsFile)) continue;
20233
+ const agentsFile = (0, import_node_path47.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
20234
+ if (!(0, import_node_fs47.existsSync)(agentsFile)) continue;
20083
20235
  let text7;
20084
20236
  try {
20085
- text7 = (0, import_node_fs46.readFileSync)(agentsFile, "utf8");
20237
+ text7 = (0, import_node_fs47.readFileSync)(agentsFile, "utf8");
20086
20238
  } catch {
20087
20239
  continue;
20088
20240
  }
@@ -20106,7 +20258,7 @@ function resolveConductorCursorAgentId(workspacePath) {
20106
20258
  return best?.agentId ?? null;
20107
20259
  }
20108
20260
  async function adoptThread(input) {
20109
- if (!(0, import_node_fs46.existsSync)(input.worktreePath)) {
20261
+ if (!(0, import_node_fs47.existsSync)(input.worktreePath)) {
20110
20262
  throw new Error(`Worktree not found: ${input.worktreePath}`);
20111
20263
  }
20112
20264
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -20135,18 +20287,18 @@ function conductorDbPath() {
20135
20287
  return CONDUCTOR_DB;
20136
20288
  }
20137
20289
  function listConductorWorkspaces() {
20138
- if (!(0, import_node_fs46.existsSync)(CONDUCTOR_DB)) {
20290
+ if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
20139
20291
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
20140
20292
  }
20141
- const tmp = (0, import_node_fs46.mkdtempSync)((0, import_node_path45.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20142
- const snapshot = (0, import_node_path45.join)(tmp, "conductor.db");
20293
+ const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path47.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20294
+ const snapshot = (0, import_node_path47.join)(tmp, "conductor.db");
20143
20295
  try {
20144
- (0, import_node_fs46.copyFileSync)(CONDUCTOR_DB, snapshot);
20296
+ (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
20145
20297
  for (const suffix of ["-wal", "-shm"]) {
20146
20298
  const src = `${CONDUCTOR_DB}${suffix}`;
20147
- if ((0, import_node_fs46.existsSync)(src)) {
20299
+ if ((0, import_node_fs47.existsSync)(src)) {
20148
20300
  try {
20149
- (0, import_node_fs46.copyFileSync)(src, `${snapshot}${suffix}`);
20301
+ (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
20150
20302
  } catch {
20151
20303
  }
20152
20304
  }
@@ -20222,22 +20374,22 @@ function listConductorWorkspaces() {
20222
20374
  db.close();
20223
20375
  }
20224
20376
  } finally {
20225
- (0, import_node_fs46.rmSync)(tmp, { recursive: true, force: true });
20377
+ (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
20226
20378
  }
20227
20379
  }
20228
20380
  function importConductorWorkspace(workspaceId) {
20229
- if (!(0, import_node_fs46.existsSync)(CONDUCTOR_DB)) {
20381
+ if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
20230
20382
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
20231
20383
  }
20232
- const tmp = (0, import_node_fs46.mkdtempSync)((0, import_node_path45.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20233
- const snapshot = (0, import_node_path45.join)(tmp, "conductor.db");
20384
+ const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path47.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
20385
+ const snapshot = (0, import_node_path47.join)(tmp, "conductor.db");
20234
20386
  try {
20235
- (0, import_node_fs46.copyFileSync)(CONDUCTOR_DB, snapshot);
20387
+ (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
20236
20388
  for (const suffix of ["-wal", "-shm"]) {
20237
20389
  const src = `${CONDUCTOR_DB}${suffix}`;
20238
- if ((0, import_node_fs46.existsSync)(src)) {
20390
+ if ((0, import_node_fs47.existsSync)(src)) {
20239
20391
  try {
20240
- (0, import_node_fs46.copyFileSync)(src, `${snapshot}${suffix}`);
20392
+ (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
20241
20393
  } catch {
20242
20394
  }
20243
20395
  }
@@ -20255,7 +20407,7 @@ function importConductorWorkspace(workspaceId) {
20255
20407
  ).get(workspaceId);
20256
20408
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
20257
20409
  const worktreePath = String(row.workspacePath);
20258
- if (!(0, import_node_fs46.existsSync)(worktreePath)) {
20410
+ if (!(0, import_node_fs47.existsSync)(worktreePath)) {
20259
20411
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
20260
20412
  }
20261
20413
  let sessionId = null;
@@ -20318,31 +20470,31 @@ function importConductorWorkspace(workspaceId) {
20318
20470
  db.close();
20319
20471
  }
20320
20472
  } finally {
20321
- (0, import_node_fs46.rmSync)(tmp, { recursive: true, force: true });
20473
+ (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
20322
20474
  }
20323
20475
  }
20324
20476
  async function importConductorWorkspaceAsync(workspaceId) {
20325
20477
  return importConductorWorkspace(workspaceId);
20326
20478
  }
20327
- var import_node_child_process5, import_node_fs46, import_node_os14, import_node_path45, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
20479
+ var import_node_child_process5, import_node_fs47, import_node_os14, import_node_path47, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
20328
20480
  var init_adopt = __esm({
20329
20481
  "src/threads/adopt.ts"() {
20330
20482
  "use strict";
20331
20483
  import_node_child_process5 = require("child_process");
20332
- import_node_fs46 = require("fs");
20484
+ import_node_fs47 = require("fs");
20333
20485
  import_node_os14 = require("os");
20334
- import_node_path45 = require("path");
20486
+ import_node_path47 = require("path");
20335
20487
  import_node_module4 = require("module");
20336
20488
  init_worktree();
20337
20489
  init_thread_store();
20338
- CONDUCTOR_APP_SUPPORT = (0, import_node_path45.join)(
20490
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path47.join)(
20339
20491
  process.env.HOME ?? "",
20340
20492
  "Library",
20341
20493
  "Application Support",
20342
20494
  "com.conductor.app"
20343
20495
  );
20344
- CONDUCTOR_DB = (0, import_node_path45.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
20345
- CURSOR_SDK_STORE = (0, import_node_path45.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
20496
+ CONDUCTOR_DB = (0, import_node_path47.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
20497
+ CURSOR_SDK_STORE = (0, import_node_path47.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
20346
20498
  }
20347
20499
  });
20348
20500
 
@@ -20409,7 +20561,7 @@ async function openStackLayer(input, _onSetupLine) {
20409
20561
  let createdWorktree = false;
20410
20562
  const trees = await listWorktrees(repoPath);
20411
20563
  const checkedOut = trees.find((w) => w.branch === branchName);
20412
- if (checkedOut?.path && (0, import_node_fs47.existsSync)(checkedOut.path)) {
20564
+ if (checkedOut?.path && (0, import_node_fs48.existsSync)(checkedOut.path)) {
20413
20565
  if (input.reuseExistingWorktree !== false) {
20414
20566
  worktreePath = checkedOut.path;
20415
20567
  } else {
@@ -20551,7 +20703,7 @@ async function initStackFromThread(input, onSetupLine) {
20551
20703
  async function createPrStack(input, onSetupLine) {
20552
20704
  await requireAgent(input.agent);
20553
20705
  const repoPath = await resolveRepoRoot(input.repoPath);
20554
- if (!(0, import_node_fs47.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
20706
+ if (!(0, import_node_fs48.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
20555
20707
  if (!input.branches.length) throw new Error("At least one branch name required");
20556
20708
  const status = await detectGhStack(repoPath);
20557
20709
  if (!status.available) throw new Error(status.reason);
@@ -20618,7 +20770,7 @@ async function createPrStack(input, onSetupLine) {
20618
20770
  }
20619
20771
  }
20620
20772
  const claimed = new Set(threads.map((t) => t.worktreePath));
20621
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs47.existsSync)(bootstrap.worktreePath)) {
20773
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs48.existsSync)(bootstrap.worktreePath)) {
20622
20774
  try {
20623
20775
  await removeWorktree(repoPath, bootstrap.worktreePath, {
20624
20776
  deleteBranch: bootstrap.branchName
@@ -20638,11 +20790,11 @@ function stackAgentDefaultsFrom(input) {
20638
20790
  planMode: input.planMode
20639
20791
  };
20640
20792
  }
20641
- var import_node_fs47;
20793
+ var import_node_fs48;
20642
20794
  var init_stack_layers = __esm({
20643
20795
  "src/threads/stack-layers.ts"() {
20644
20796
  "use strict";
20645
- import_node_fs47 = require("fs");
20797
+ import_node_fs48 = require("fs");
20646
20798
  init_detect();
20647
20799
  init_run();
20648
20800
  init_stack();
@@ -20655,7 +20807,7 @@ var init_stack_layers = __esm({
20655
20807
 
20656
20808
  // src/diff/diff.ts
20657
20809
  async function inspectGitWorktree(worktreePath) {
20658
- if (!worktreePath || !(0, import_node_fs48.existsSync)(worktreePath)) return "missing_worktree";
20810
+ if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) return "missing_worktree";
20659
20811
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
20660
20812
  reject: false
20661
20813
  });
@@ -20663,7 +20815,7 @@ async function inspectGitWorktree(worktreePath) {
20663
20815
  return "ok";
20664
20816
  }
20665
20817
  async function initializeGitRepository(worktreePath) {
20666
- if (!worktreePath || !(0, import_node_fs48.existsSync)(worktreePath)) {
20818
+ if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) {
20667
20819
  throw new Error("Worktree not found");
20668
20820
  }
20669
20821
  const status = await inspectGitWorktree(worktreePath);
@@ -20797,11 +20949,11 @@ new file mode 100644
20797
20949
  };
20798
20950
  }
20799
20951
  async function untrackedPatch(worktreePath, path2, maxHunk) {
20800
- const abs = (0, import_node_path46.join)(worktreePath, path2);
20952
+ const abs = (0, import_node_path48.join)(worktreePath, path2);
20801
20953
  try {
20802
- const st = (0, import_node_fs48.statSync)(abs);
20954
+ const st = (0, import_node_fs49.statSync)(abs);
20803
20955
  if (st.isFile() && st.size > maxHunk) {
20804
- const buf = (0, import_node_fs48.readFileSync)(abs).subarray(0, maxHunk);
20956
+ const buf = (0, import_node_fs49.readFileSync)(abs).subarray(0, maxHunk);
20805
20957
  return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
20806
20958
  }
20807
20959
  } catch {
@@ -21266,6 +21418,15 @@ async function getDiff(worktreePath, repoPath, opts) {
21266
21418
  mergeBase: needsMergeBase ? mergeBase : null
21267
21419
  };
21268
21420
  }
21421
+ function statWorktreePath(worktreePath, relativePath) {
21422
+ assertSafeRelativePath(relativePath);
21423
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21424
+ if (!(0, import_node_fs49.existsSync)(abs)) return "missing";
21425
+ const st = (0, import_node_fs49.statSync)(abs);
21426
+ if (st.isDirectory()) return "dir";
21427
+ if (st.isFile()) return "file";
21428
+ return "missing";
21429
+ }
21269
21430
  async function listWorktreeFiles(worktreePath, opts) {
21270
21431
  const maxFiles = opts?.maxFiles ?? 5e3;
21271
21432
  const tracked = await git(["ls-files", "-z"], worktreePath, { reject: false });
@@ -21290,8 +21451,8 @@ function isImageRelativePath(relativePath) {
21290
21451
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
21291
21452
  assertSafeRelativePath(relativePath);
21292
21453
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
21293
- const abs = (0, import_node_path46.join)(worktreePath, relativePath);
21294
- const st = (0, import_node_fs48.statSync)(abs);
21454
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21455
+ const st = (0, import_node_fs49.statSync)(abs);
21295
21456
  if (!st.isFile()) {
21296
21457
  throw new Error(`Not a file: ${relativePath}`);
21297
21458
  }
@@ -21300,7 +21461,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
21300
21461
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
21301
21462
  );
21302
21463
  }
21303
- const buf = (0, import_node_fs48.readFileSync)(abs);
21464
+ const buf = (0, import_node_fs49.readFileSync)(abs);
21304
21465
  return {
21305
21466
  path: relativePath,
21306
21467
  contentBase64: buf.toString("base64"),
@@ -21310,12 +21471,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
21310
21471
  function readWorktreeFile(worktreePath, relativePath, opts) {
21311
21472
  assertSafeRelativePath(relativePath);
21312
21473
  const maxBytes = opts?.maxBytes ?? 2e5;
21313
- const abs = (0, import_node_path46.join)(worktreePath, relativePath);
21314
- const st = (0, import_node_fs48.statSync)(abs);
21474
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21475
+ const st = (0, import_node_fs49.statSync)(abs);
21315
21476
  if (!st.isFile()) {
21316
21477
  throw new Error(`Not a file: ${relativePath}`);
21317
21478
  }
21318
- const buf = (0, import_node_fs48.readFileSync)(abs);
21479
+ const buf = (0, import_node_fs49.readFileSync)(abs);
21319
21480
  if (isImageRelativePath(relativePath)) {
21320
21481
  const maxImageBytes = Math.max(maxBytes, 15e6);
21321
21482
  const truncated2 = buf.length > maxImageBytes;
@@ -21358,9 +21519,9 @@ function assertSafeRelativePath(relativePath) {
21358
21519
  }
21359
21520
  function writeWorktreeFile(worktreePath, relativePath, content) {
21360
21521
  assertSafeRelativePath(relativePath);
21361
- const abs = (0, import_node_path46.join)(worktreePath, relativePath);
21362
- (0, import_node_fs48.mkdirSync)((0, import_node_path46.dirname)(abs), { recursive: true });
21363
- (0, import_node_fs48.writeFileSync)(abs, content, "utf8");
21522
+ const abs = (0, import_node_path48.join)(worktreePath, relativePath);
21523
+ (0, import_node_fs49.mkdirSync)((0, import_node_path48.dirname)(abs), { recursive: true });
21524
+ (0, import_node_fs49.writeFileSync)(abs, content, "utf8");
21364
21525
  return { path: relativePath };
21365
21526
  }
21366
21527
  async function getWorktreeDirtyStat(worktreePath) {
@@ -21400,12 +21561,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
21400
21561
  truncated: full.files.length > maxFiles
21401
21562
  };
21402
21563
  }
21403
- var import_node_fs48, import_node_path46, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
21564
+ var import_node_fs49, import_node_path48, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
21404
21565
  var init_diff = __esm({
21405
21566
  "src/diff/diff.ts"() {
21406
21567
  "use strict";
21407
- import_node_fs48 = require("fs");
21408
- import_node_path46 = require("path");
21568
+ import_node_fs49 = require("fs");
21569
+ import_node_path48 = require("path");
21409
21570
  init_run();
21410
21571
  init_worktree();
21411
21572
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -21762,7 +21923,7 @@ function parseFrontmatter(content) {
21762
21923
  }
21763
21924
  function readSkill(skillMd, source) {
21764
21925
  try {
21765
- const content = (0, import_node_fs49.readFileSync)(skillMd, "utf8");
21926
+ const content = (0, import_node_fs50.readFileSync)(skillMd, "utf8");
21766
21927
  const { name: fmName, description } = parseFrontmatter(content);
21767
21928
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
21768
21929
  const name = fmName || dirName;
@@ -21781,19 +21942,19 @@ function readSkill(skillMd, source) {
21781
21942
  }
21782
21943
  }
21783
21944
  function scanSkillsDir(dir, source, out) {
21784
- if (!(0, import_node_fs49.existsSync)(dir)) return;
21945
+ if (!(0, import_node_fs50.existsSync)(dir)) return;
21785
21946
  let entries;
21786
21947
  try {
21787
- entries = (0, import_node_fs49.readdirSync)(dir);
21948
+ entries = (0, import_node_fs50.readdirSync)(dir);
21788
21949
  } catch {
21789
21950
  return;
21790
21951
  }
21791
21952
  for (const entry of entries) {
21792
21953
  if (entry.startsWith(".")) continue;
21793
- const skillMd = (0, import_node_path47.join)(dir, entry, "SKILL.md");
21794
- if (!(0, import_node_fs49.existsSync)(skillMd)) continue;
21954
+ const skillMd = (0, import_node_path49.join)(dir, entry, "SKILL.md");
21955
+ if (!(0, import_node_fs50.existsSync)(skillMd)) continue;
21795
21956
  try {
21796
- if (!(0, import_node_fs49.statSync)(skillMd).isFile()) continue;
21957
+ if (!(0, import_node_fs50.statSync)(skillMd).isFile()) continue;
21797
21958
  } catch {
21798
21959
  continue;
21799
21960
  }
@@ -21802,24 +21963,24 @@ function scanSkillsDir(dir, source, out) {
21802
21963
  }
21803
21964
  }
21804
21965
  function scanClaudePluginSkills(pluginsRoot, out) {
21805
- if (!(0, import_node_fs49.existsSync)(pluginsRoot)) return;
21966
+ if (!(0, import_node_fs50.existsSync)(pluginsRoot)) return;
21806
21967
  const walk = (dir, depth, lookingForSkillsDir) => {
21807
21968
  if (depth > 7) return;
21808
21969
  let entries;
21809
21970
  try {
21810
- entries = (0, import_node_fs49.readdirSync)(dir);
21971
+ entries = (0, import_node_fs50.readdirSync)(dir);
21811
21972
  } catch {
21812
21973
  return;
21813
21974
  }
21814
21975
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
21815
- const skill = readSkill((0, import_node_path47.join)(dir, "SKILL.md"), "cli");
21976
+ const skill = readSkill((0, import_node_path49.join)(dir, "SKILL.md"), "cli");
21816
21977
  if (skill) out.push(skill);
21817
21978
  }
21818
21979
  for (const entry of entries) {
21819
21980
  if (entry === "node_modules" || entry === ".git") continue;
21820
- const full = (0, import_node_path47.join)(dir, entry);
21981
+ const full = (0, import_node_path49.join)(dir, entry);
21821
21982
  try {
21822
- if (!(0, import_node_fs49.statSync)(full).isDirectory()) continue;
21983
+ if (!(0, import_node_fs50.statSync)(full).isDirectory()) continue;
21823
21984
  } catch {
21824
21985
  continue;
21825
21986
  }
@@ -21837,17 +21998,17 @@ function discoverSkills(worktreePath) {
21837
21998
  const home = (0, import_node_os15.homedir)();
21838
21999
  const collected = [];
21839
22000
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
21840
- scanSkillsDir((0, import_node_path47.join)(worktreePath, rel), "workspace", collected);
22001
+ scanSkillsDir((0, import_node_path49.join)(worktreePath, rel), "workspace", collected);
21841
22002
  }
21842
22003
  for (const abs of [
21843
- (0, import_node_path47.join)(home, ".claude/skills"),
21844
- (0, import_node_path47.join)(home, ".cursor/skills"),
21845
- (0, import_node_path47.join)(home, ".sideboard/skills"),
21846
- (0, import_node_path47.join)(home, ".brightsy/skills")
22004
+ (0, import_node_path49.join)(home, ".claude/skills"),
22005
+ (0, import_node_path49.join)(home, ".cursor/skills"),
22006
+ (0, import_node_path49.join)(home, ".sideboard/skills"),
22007
+ (0, import_node_path49.join)(home, ".brightsy/skills")
21847
22008
  ]) {
21848
22009
  scanSkillsDir(abs, "user", collected);
21849
22010
  }
21850
- scanClaudePluginSkills((0, import_node_path47.join)(home, ".claude/plugins"), collected);
22011
+ scanClaudePluginSkills((0, import_node_path49.join)(home, ".claude/plugins"), collected);
21851
22012
  collected.push(...bundledSkills());
21852
22013
  const rank = {
21853
22014
  workspace: 0,
@@ -21873,7 +22034,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
21873
22034
  \u2026(truncated)` : body;
21874
22035
  }
21875
22036
  }
21876
- const raw = (0, import_node_fs49.readFileSync)(skillPath, "utf8");
22037
+ const raw = (0, import_node_fs50.readFileSync)(skillPath, "utf8");
21877
22038
  if (raw.startsWith("---")) {
21878
22039
  const end = raw.indexOf("\n---", 3);
21879
22040
  if (end >= 0) {
@@ -21887,13 +22048,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
21887
22048
 
21888
22049
  \u2026(truncated)` : raw;
21889
22050
  }
21890
- var import_node_fs49, import_node_os15, import_node_path47, BUNDLED_SKILL_PREFIX;
22051
+ var import_node_fs50, import_node_os15, import_node_path49, BUNDLED_SKILL_PREFIX;
21891
22052
  var init_discover = __esm({
21892
22053
  "src/skills/discover.ts"() {
21893
22054
  "use strict";
21894
- import_node_fs49 = require("fs");
22055
+ import_node_fs50 = require("fs");
21895
22056
  import_node_os15 = require("os");
21896
- import_node_path47 = require("path");
22057
+ import_node_path49 = require("path");
21897
22058
  init_long_running();
21898
22059
  BUNDLED_SKILL_PREFIX = "bundled:";
21899
22060
  }
@@ -22042,10 +22203,22 @@ var init_consume_attachments = __esm({
22042
22203
  });
22043
22204
 
22044
22205
  // src/skills/detached-job-path.ts
22206
+ function compiledModuleDir() {
22207
+ const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
22208
+ if (cjsDir) return cjsDir;
22209
+ try {
22210
+ const url = import_meta3.url;
22211
+ if (typeof url === "string" && url.length > 0) {
22212
+ return (0, import_node_path50.dirname)((0, import_node_url3.fileURLToPath)(url));
22213
+ }
22214
+ } catch {
22215
+ }
22216
+ return null;
22217
+ }
22045
22218
  function detachedJobScriptIn(dir) {
22046
22219
  for (const name of DETACHED_JOB_FILENAMES) {
22047
- const script = (0, import_node_path48.join)(dir, "scripts", name);
22048
- if ((0, import_node_fs50.existsSync)(script)) return script;
22220
+ const script = (0, import_node_path50.join)(dir, "scripts", name);
22221
+ if ((0, import_node_fs51.existsSync)(script)) return script;
22049
22222
  }
22050
22223
  return null;
22051
22224
  }
@@ -22057,11 +22230,12 @@ function packagedDetachedJobPath() {
22057
22230
  function resolveDetachedJobScript() {
22058
22231
  const packaged = packagedDetachedJobPath();
22059
22232
  if (packaged) return packaged;
22060
- let dir = (0, import_node_path48.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
22233
+ let dir = compiledModuleDir();
22234
+ if (!dir) return null;
22061
22235
  for (let i = 0; i < 8; i++) {
22062
22236
  const candidate = detachedJobScriptIn(dir);
22063
22237
  if (candidate) return candidate;
22064
- const parent = (0, import_node_path48.dirname)(dir);
22238
+ const parent = (0, import_node_path50.dirname)(dir);
22065
22239
  if (parent === dir) break;
22066
22240
  dir = parent;
22067
22241
  }
@@ -22072,12 +22246,12 @@ function formatDetachedJobInvoke(scriptPath) {
22072
22246
  if (resolved) return `node ${JSON.stringify(resolved)}`;
22073
22247
  return "node scripts/detached-job.cjs";
22074
22248
  }
22075
- var import_node_fs50, import_node_path48, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
22249
+ var import_node_fs51, import_node_path50, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
22076
22250
  var init_detached_job_path = __esm({
22077
22251
  "src/skills/detached-job-path.ts"() {
22078
22252
  "use strict";
22079
- import_node_fs50 = require("fs");
22080
- import_node_path48 = require("path");
22253
+ import_node_fs51 = require("fs");
22254
+ import_node_path50 = require("path");
22081
22255
  import_node_url3 = require("url");
22082
22256
  init_packaged_runtime();
22083
22257
  import_meta3 = {};
@@ -22259,9 +22433,9 @@ function formatPrGateDirective() {
22259
22433
  }
22260
22434
  function formatProcessGuideDirective(opts) {
22261
22435
  const worktree = opts?.worktreePath?.trim();
22262
- const hasGraphSkill = !!worktree && (0, import_node_fs51.existsSync)((0, import_node_path49.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
22263
- const hasReviewSkill = !!worktree && (0, import_node_fs51.existsSync)((0, import_node_path49.join)(worktree, ".claude/skills/review/SKILL.md"));
22264
- const hasInstallSkill = !!worktree && (0, import_node_fs51.existsSync)((0, import_node_path49.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
22436
+ const hasGraphSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
22437
+ const hasReviewSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/review/SKILL.md"));
22438
+ const hasInstallSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path51.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
22265
22439
  return [
22266
22440
  "Process guides (recurring work only):",
22267
22441
  hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
@@ -22299,12 +22473,12 @@ function formatArtifactDirective() {
22299
22473
  function formatUiReminder() {
22300
22474
  return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
22301
22475
  }
22302
- var import_node_fs51, import_node_path49, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
22476
+ var import_node_fs52, import_node_path51, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
22303
22477
  var init_instructions = __esm({
22304
22478
  "src/agents/instructions.ts"() {
22305
22479
  "use strict";
22306
- import_node_fs51 = require("fs");
22307
- import_node_path49 = require("path");
22480
+ import_node_fs52 = require("fs");
22481
+ import_node_path51 = require("path");
22308
22482
  init_git_auth_mode();
22309
22483
  init_branch_prefix();
22310
22484
  init_worktree_labels();
@@ -22690,40 +22864,40 @@ __export(plan_file_exports, {
22690
22864
  writePlanFile: () => writePlanFile
22691
22865
  });
22692
22866
  function ensureAttachmentsGitignore(worktreePath) {
22693
- const gitignoreAbs = (0, import_node_path50.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
22694
- if ((0, import_node_fs52.existsSync)(gitignoreAbs)) return;
22695
- (0, import_node_fs52.mkdirSync)((0, import_node_path50.dirname)(gitignoreAbs), { recursive: true });
22696
- (0, import_node_fs52.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
22867
+ const gitignoreAbs = (0, import_node_path52.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
22868
+ if ((0, import_node_fs53.existsSync)(gitignoreAbs)) return;
22869
+ (0, import_node_fs53.mkdirSync)((0, import_node_path52.dirname)(gitignoreAbs), { recursive: true });
22870
+ (0, import_node_fs53.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
22697
22871
  }
22698
22872
  function planFileAbs(worktreePath) {
22699
- return (0, import_node_path50.join)(worktreePath, PLAN_FILE_REL);
22873
+ return (0, import_node_path52.join)(worktreePath, PLAN_FILE_REL);
22700
22874
  }
22701
22875
  function readTextIfPresent2(abs) {
22702
- if (!(0, import_node_fs52.existsSync)(abs)) return null;
22876
+ if (!(0, import_node_fs53.existsSync)(abs)) return null;
22703
22877
  try {
22704
- const content = (0, import_node_fs52.readFileSync)(abs, "utf8");
22878
+ const content = (0, import_node_fs53.readFileSync)(abs, "utf8");
22705
22879
  return content.trim() ? content : null;
22706
22880
  } catch {
22707
22881
  return null;
22708
22882
  }
22709
22883
  }
22710
22884
  function readPlanFile(worktreePath) {
22711
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path50.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path50.join)(worktreePath, LEGACY_PLAN_FILE_REL));
22885
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path52.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path52.join)(worktreePath, LEGACY_PLAN_FILE_REL));
22712
22886
  }
22713
22887
  function writePlanFile(worktreePath, content) {
22714
22888
  ensureAttachmentsGitignore(worktreePath);
22715
22889
  const abs = planFileAbs(worktreePath);
22716
- (0, import_node_fs52.mkdirSync)((0, import_node_path50.dirname)(abs), { recursive: true });
22890
+ (0, import_node_fs53.mkdirSync)((0, import_node_path52.dirname)(abs), { recursive: true });
22717
22891
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
22718
- (0, import_node_fs52.writeFileSync)(abs, body, "utf8");
22892
+ (0, import_node_fs53.writeFileSync)(abs, body, "utf8");
22719
22893
  return PLAN_FILE_REL;
22720
22894
  }
22721
- var import_node_fs52, import_node_path50;
22895
+ var import_node_fs53, import_node_path52;
22722
22896
  var init_plan_file = __esm({
22723
22897
  "src/plan/plan-file.ts"() {
22724
22898
  "use strict";
22725
- import_node_fs52 = require("fs");
22726
- import_node_path50 = require("path");
22899
+ import_node_fs53 = require("fs");
22900
+ import_node_path52 = require("path");
22727
22901
  init_workspace_scratch();
22728
22902
  init_plan_present();
22729
22903
  init_plan_present();
@@ -22785,9 +22959,9 @@ function recoverFinishedCursorRun(opts) {
22785
22959
  return best;
22786
22960
  }
22787
22961
  function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
22788
- if (!(0, import_node_fs53.existsSync)(runsPath)) return null;
22962
+ if (!(0, import_node_fs54.existsSync)(runsPath)) return null;
22789
22963
  try {
22790
- const lines = (0, import_node_fs53.readFileSync)(runsPath, "utf8").split("\n");
22964
+ const lines = (0, import_node_fs54.readFileSync)(runsPath, "utf8").split("\n");
22791
22965
  let best = null;
22792
22966
  for (const line of lines) {
22793
22967
  const trimmed = line.trim();
@@ -22813,11 +22987,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
22813
22987
  return null;
22814
22988
  }
22815
22989
  }
22816
- var import_node_fs53;
22990
+ var import_node_fs54;
22817
22991
  var init_cursor_recover = __esm({
22818
22992
  "src/agents/cursor-recover.ts"() {
22819
22993
  "use strict";
22820
- import_node_fs53 = require("fs");
22994
+ import_node_fs54 = require("fs");
22821
22995
  init_cursor_store();
22822
22996
  }
22823
22997
  });
@@ -22960,17 +23134,18 @@ async function startOrchestration(opts) {
22960
23134
  }
22961
23135
  return updated;
22962
23136
  }
22963
- var import_node_events, import_node_fs54, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
23137
+ var import_node_events, import_node_fs55, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
22964
23138
  var init_orchestrator = __esm({
22965
23139
  "src/orchestrator/orchestrator.ts"() {
22966
23140
  "use strict";
22967
23141
  import_node_events = require("events");
22968
23142
  init_outbound_watch();
22969
- import_node_fs54 = require("fs");
23143
+ import_node_fs55 = require("fs");
22970
23144
  init_error_detail();
22971
23145
  init_run();
22972
23146
  init_stale_lock();
22973
23147
  init_spawn();
23148
+ init_turn_trace();
22974
23149
  init_agents();
22975
23150
  init_worktree();
22976
23151
  init_stack();
@@ -23131,7 +23306,7 @@ var init_orchestrator = __esm({
23131
23306
  this.lightReconcileAt.set(repoPath, Date.now());
23132
23307
  for (const thread of listThreads()) {
23133
23308
  if (isGlobalThread(thread) || thread.repoPath !== repoPath) continue;
23134
- if (!(0, import_node_fs54.existsSync)(thread.worktreePath)) {
23309
+ if (!(0, import_node_fs55.existsSync)(thread.worktreePath)) {
23135
23310
  setStatus(thread.id, "broken", "Worktree missing on disk");
23136
23311
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
23137
23312
  }
@@ -23160,7 +23335,7 @@ var init_orchestrator = __esm({
23160
23335
  }
23161
23336
  continue;
23162
23337
  }
23163
- if (!(0, import_node_fs54.existsSync)(thread.worktreePath)) {
23338
+ if (!(0, import_node_fs55.existsSync)(thread.worktreePath)) {
23164
23339
  setStatus(thread.id, "broken", "Worktree missing on disk");
23165
23340
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
23166
23341
  continue;
@@ -23226,7 +23401,7 @@ var init_orchestrator = __esm({
23226
23401
  }
23227
23402
  if (thread.queue.length > 0) {
23228
23403
  this.haltDrain.delete(thread.id);
23229
- void this.drainQueue(thread.id);
23404
+ this.armDrain(thread.id);
23230
23405
  }
23231
23406
  }
23232
23407
  }
@@ -23562,7 +23737,7 @@ var init_orchestrator = __esm({
23562
23737
  this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
23563
23738
  }
23564
23739
  if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
23565
- void this.drainQueue(thread.id);
23740
+ this.armDrain(thread.id);
23566
23741
  }
23567
23742
  return this.requireThread(thread.id);
23568
23743
  });
@@ -23642,9 +23817,15 @@ var init_orchestrator = __esm({
23642
23817
  if (inFlight || foreignLive) {
23643
23818
  this.stop(thread.id, { clearQueue: false, continueQueue: true });
23644
23819
  }
23645
- void this.drainQueue(thread.id);
23820
+ this.armDrain(thread.id);
23646
23821
  return this.requireThread(thread.id);
23647
23822
  }
23823
+ armDrain(threadId) {
23824
+ void this.drainQueue(threadId).catch((err) => {
23825
+ const detail = err instanceof Error ? err.message : String(err);
23826
+ console.error(`[sideboard] drainQueue ${threadId}: ${detail}`);
23827
+ });
23828
+ }
23648
23829
  async drainQueue(threadId) {
23649
23830
  if (this.draining.has(threadId)) return;
23650
23831
  this.draining.add(threadId);
@@ -23716,196 +23897,205 @@ var init_orchestrator = __esm({
23716
23897
  this.emit({ type: "status_changed", threadId, status: "running" });
23717
23898
  this.emit({ type: "turn_started", threadId, prompt });
23718
23899
  try {
23719
- const baseline = await captureTurnBaseline(thread.worktreePath);
23720
- if (baseline) this.turnBaselines.set(threadId, baseline);
23721
- } catch {
23722
- }
23723
- try {
23724
- const compact = await maybeCompactContext(thread);
23725
- if (compact.didCompact) {
23726
- thread = updateThread(threadId, {
23727
- messages: compact.thread.messages,
23728
- sessionId: compact.thread.sessionId
23729
- });
23730
- this.emit({
23731
- type: "context_compacted",
23732
- threadId,
23733
- olderCount: compact.olderCount ?? 0,
23734
- method: compact.method ?? "extractive"
23735
- });
23900
+ try {
23901
+ const baseline = await captureTurnBaseline(thread.worktreePath);
23902
+ if (baseline) this.turnBaselines.set(threadId, baseline);
23903
+ } catch {
23736
23904
  }
23737
- } catch (err) {
23738
- const message = err instanceof Error ? err.message : String(err);
23739
- this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
23740
- thread = this.requireThread(threadId);
23741
- }
23742
- const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
23743
- const parked = takePendingTurnAttachments(thread);
23744
- const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
23745
- appendMessage(threadId, {
23746
- role: "user",
23747
- text: prompt,
23748
- ...sentAttachments ? { attachments: sentAttachments } : {},
23749
- ...autoContinue ? { origin: "continue" } : {},
23750
- ts: (/* @__PURE__ */ new Date()).toISOString()
23751
- });
23752
- thread = this.requireThread(threadId);
23753
- const gitPrompt = expandCanonicalGitRequest(prompt);
23754
- const { agentPrompt: expandedPrompt } = expandComposerPrompt(
23755
- thread.worktreePath,
23756
- gitPrompt,
23757
- {
23758
- attachments: autoContinue ? [] : sentAttachments ?? []
23905
+ try {
23906
+ const compact = await maybeCompactContext(thread);
23907
+ if (compact.didCompact) {
23908
+ thread = updateThread(threadId, {
23909
+ messages: compact.thread.messages,
23910
+ sessionId: compact.thread.sessionId
23911
+ });
23912
+ this.emit({
23913
+ type: "context_compacted",
23914
+ threadId,
23915
+ olderCount: compact.olderCount ?? 0,
23916
+ method: compact.method ?? "extractive"
23917
+ });
23918
+ }
23919
+ } catch (err) {
23920
+ const message = err instanceof Error ? err.message : String(err);
23921
+ this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
23922
+ thread = this.requireThread(threadId);
23759
23923
  }
23760
- );
23761
- const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
23762
- expandedPrompt.trim()
23763
- );
23764
- const orchestrationReminder = isOrchestratorThread(thread) ? [
23765
- coordinatorTurnReminder({
23766
- parentId: threadId,
23767
- goal: thread.sourceRef || thread.title
23768
- }),
23769
- slackInbound ? [
23770
- "This turn is a Slack DM or @mention. Your reply is posted back in Slack \u2014 keep it concise. Sideboard signs it with this Mac's destination name; do not prefix the name yourself.",
23771
- SLACK_REPLY_FORMATTING
23772
- ].join("\n") : null
23773
- ].filter(Boolean).join("\n") : null;
23774
- const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
23775
- const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder() : null;
23776
- const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
23777
- const optionalServicesReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatOptionalServicesReminder(loadAppSettings().integrations) : null;
23778
- const issueTicket = issueTicketFromThread(thread, resolveEffectiveIssueSource());
23779
- const issueToolsReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatIssueToolsReminder({
23780
- linear: isLinearConnected(),
23781
- abletime: isAbleTimeConnected(),
23782
- github: true,
23783
- ticketId: issueTicket?.id,
23784
- ticketProvider: issueTicket?.provider
23785
- }) : null;
23786
- const viewerContextReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatViewerContextReminder() : null;
23787
- const reviewWriteGateReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && isReviewWriteGatedThread(
23788
- thread,
23789
- thread.worktreePath ? threadsSharingWorktree(thread.worktreePath) : []
23790
- ) ? formatReviewWriteGateReminder() : null;
23791
- const slackReplyContext = formatSlackRepliesForTurn(
23792
- pendingSlackExternalReplies(thread.messages)
23793
- );
23794
- const turnReminders = [
23795
- worktreeReminder,
23796
- optionalServicesReminder,
23797
- issueToolsReminder,
23798
- reviewWriteGateReminder,
23799
- viewerContextReminder,
23800
- artifactReminder,
23801
- longRunningReminder
23802
- ].filter(Boolean).join("\n\n") || void 0;
23803
- const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(prompt) ? formatPrGateDirective() : null;
23804
- const agentPrompt = [
23805
- thread.planMode ? PLAN_MODE_INSTRUCTION : null,
23806
- orchestrationReminder,
23807
- prGateDirective,
23808
- slackReplyContext,
23809
- expandedPrompt
23810
- ].filter(Boolean).join("\n\n");
23811
- if (!autoContinue && sentAttachments) {
23812
- updateThread(threadId, { pendingTurnAttachments: [] });
23813
- }
23814
- const adapter = getAdapter(thread.agent);
23815
- const resolved = await adapter.resolveSessionId(thread.worktreePath, thread.sessionId);
23816
- if (resolved && resolved !== thread.sessionId) {
23817
- updateThread(threadId, { sessionId: resolved });
23818
- }
23819
- const fresh = this.requireThread(threadId);
23820
- if (!fresh.worktreePath?.trim()) {
23821
- throw new Error(
23822
- `Thread ${threadId} has no worktreePath \u2014 refusing to start an agent outside an isolated worktree`
23924
+ const promptText = typeof prompt === "string" ? prompt : "";
23925
+ const autoContinue = isJobContinuePrompt(promptText) || promptText.startsWith("The previous agent process ended before it finished.");
23926
+ const parked = takePendingTurnAttachments(thread);
23927
+ const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
23928
+ appendMessage(threadId, {
23929
+ role: "user",
23930
+ text: promptText,
23931
+ ...sentAttachments ? { attachments: sentAttachments } : {},
23932
+ ...autoContinue ? { origin: "continue" } : {},
23933
+ ts: (/* @__PURE__ */ new Date()).toISOString()
23934
+ });
23935
+ traceTurn("runTurn.afterUserMessage", {
23936
+ threadId,
23937
+ agent: thread.agent,
23938
+ orch: isOrchestratorThread(thread)
23939
+ });
23940
+ thread = this.requireThread(threadId);
23941
+ const gitPrompt = expandCanonicalGitRequest(promptText);
23942
+ const { agentPrompt: expandedPrompt } = expandComposerPrompt(
23943
+ thread.worktreePath,
23944
+ gitPrompt,
23945
+ {
23946
+ attachments: autoContinue ? [] : sentAttachments ?? []
23947
+ }
23823
23948
  );
23824
- }
23825
- const isBrightsy = fresh.agent === "brightsy";
23826
- const isOrchestration = isOrchestratorThread(fresh);
23827
- const { autoRenameBranchEnabled: autoRenameBranchEnabled2, getGithubGitAuthMode: getGithubGitAuthMode2, gitBranchPrefixSetting: gitBranchPrefixSetting2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
23828
- const gitAuthMode = getGithubGitAuthMode2();
23829
- const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
23830
- githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
23831
- () => null
23832
- ),
23833
- gitAuthMode
23834
- });
23835
- const artifactDirective = isBrightsy ? null : formatArtifactDirective();
23836
- const longRunningDirective = isBrightsy || isOrchestration ? null : formatLongRunningDirective();
23837
- const optionalServicesDirective = isBrightsy || isOrchestration ? null : formatOptionalServicesDirective(loadAppSettings().integrations);
23838
- const freshIssueTicket = issueTicketFromThread(fresh, resolveEffectiveIssueSource());
23839
- const issueToolsDirective = isBrightsy || isOrchestration ? null : formatIssueToolsDirective({
23840
- linear: isLinearConnected(),
23841
- abletime: isAbleTimeConnected(),
23842
- github: true,
23843
- ticketId: freshIssueTicket?.id,
23844
- ticketProvider: freshIssueTicket?.provider
23845
- });
23846
- const reviewWriteGateDirective = isBrightsy || isOrchestration || !isReviewWriteGatedThread(
23847
- fresh,
23848
- fresh.worktreePath ? threadsSharingWorktree(fresh.worktreePath) : []
23849
- ) ? null : formatReviewWriteGateDirective();
23850
- let viewerContextDirective = null;
23851
- if (!isBrightsy && !isOrchestration) {
23852
- try {
23853
- viewerContextDirective = formatViewerContextDirective(
23854
- resolveViewerProfileForRepo(fresh.repoPath || fresh.worktreePath)
23855
- );
23856
- } catch {
23857
- viewerContextDirective = formatViewerContextDirective(
23858
- resolveViewerProfileForRepo()
23949
+ const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
23950
+ expandedPrompt.trim()
23951
+ );
23952
+ const orchestrationReminder = isOrchestratorThread(thread) ? [
23953
+ coordinatorTurnReminder({
23954
+ parentId: threadId,
23955
+ goal: thread.sourceRef || thread.title
23956
+ }),
23957
+ slackInbound ? [
23958
+ "This turn is a Slack DM or @mention. Your reply is posted back in Slack \u2014 keep it concise. Sideboard signs it with this Mac's destination name; do not prefix the name yourself.",
23959
+ SLACK_REPLY_FORMATTING
23960
+ ].join("\n") : null
23961
+ ].filter(Boolean).join("\n") : null;
23962
+ const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
23963
+ const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder() : null;
23964
+ const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
23965
+ const optionalServicesReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatOptionalServicesReminder(loadAppSettings().integrations) : null;
23966
+ const issueTicket = issueTicketFromThread(thread, resolveEffectiveIssueSource());
23967
+ const issueToolsReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatIssueToolsReminder({
23968
+ linear: isLinearConnected(),
23969
+ abletime: isAbleTimeConnected(),
23970
+ github: true,
23971
+ ticketId: issueTicket?.id,
23972
+ ticketProvider: issueTicket?.provider
23973
+ }) : null;
23974
+ const viewerContextReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatViewerContextReminder() : null;
23975
+ const reviewWriteGateReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && isReviewWriteGatedThread(
23976
+ thread,
23977
+ thread.worktreePath ? threadsSharingWorktree(thread.worktreePath) : []
23978
+ ) ? formatReviewWriteGateReminder() : null;
23979
+ const slackReplyContext = formatSlackRepliesForTurn(
23980
+ pendingSlackExternalReplies(thread.messages)
23981
+ );
23982
+ const turnReminders = [
23983
+ worktreeReminder,
23984
+ optionalServicesReminder,
23985
+ issueToolsReminder,
23986
+ reviewWriteGateReminder,
23987
+ viewerContextReminder,
23988
+ artifactReminder,
23989
+ longRunningReminder
23990
+ ].filter(Boolean).join("\n\n") || void 0;
23991
+ const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(promptText) ? formatPrGateDirective() : null;
23992
+ const agentPrompt = [
23993
+ thread.planMode ? PLAN_MODE_INSTRUCTION : null,
23994
+ orchestrationReminder,
23995
+ prGateDirective,
23996
+ slackReplyContext,
23997
+ expandedPrompt
23998
+ ].filter(Boolean).join("\n\n");
23999
+ if (!autoContinue && sentAttachments) {
24000
+ updateThread(threadId, { pendingTurnAttachments: [] });
24001
+ }
24002
+ const adapter = getAdapter(thread.agent);
24003
+ const resolved = await adapter.resolveSessionId(thread.worktreePath, thread.sessionId);
24004
+ if (resolved && resolved !== thread.sessionId) {
24005
+ updateThread(threadId, { sessionId: resolved });
24006
+ }
24007
+ const fresh = this.requireThread(threadId);
24008
+ if (!fresh.worktreePath?.trim()) {
24009
+ throw new Error(
24010
+ `Thread ${threadId} has no worktreePath \u2014 refusing to start an agent outside an isolated worktree`
23859
24011
  );
23860
24012
  }
23861
- }
23862
- const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
23863
- let renameBranchDirective = null;
23864
- if (!isBrightsy && !isOrchestration && autoRenameBranchEnabled2()) {
23865
- const { resolveGitBranchPrefix: resolveGitBranchPrefix2 } = await Promise.resolve().then(() => (init_branch_prefix(), branch_prefix_exports));
23866
- renameBranchDirective = formatRenameBranchDirective(fresh, {
23867
- customPrompt: settings?.prompts?.renameBranch,
23868
- branchPrefix: resolveGitBranchPrefix2({
23869
- setting: gitBranchPrefixSetting2()
23870
- })
24013
+ const isBrightsy = fresh.agent === "brightsy";
24014
+ const isOrchestration = isOrchestratorThread(fresh);
24015
+ const { autoRenameBranchEnabled: autoRenameBranchEnabled2, getGithubGitAuthMode: getGithubGitAuthMode2, gitBranchPrefixSetting: gitBranchPrefixSetting2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
24016
+ const gitAuthMode = getGithubGitAuthMode2();
24017
+ const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
24018
+ githubSlug: await withTimeout(
24019
+ resolveGithubRepoSlug(fresh.worktreePath),
24020
+ 8e3,
24021
+ "resolveGithubRepoSlug"
24022
+ ).catch(() => null),
24023
+ gitAuthMode
23871
24024
  });
23872
- }
23873
- let seed = null;
23874
- if (!fresh.sessionId) {
23875
- const prior = fresh.messages.slice(0, -1);
23876
- seed = isBrightsy ? buildBrightsySessionSeed(prior) : buildSessionSeed(prior);
23877
- }
23878
- let coordinatorDirective = null;
23879
- if (isOrchestration) {
23880
- if (isGlobalThread(fresh)) {
23881
- ensureGlobalCoordinatorCwd({ orchestratorThreadId: fresh.id });
24025
+ const artifactDirective = isBrightsy ? null : formatArtifactDirective();
24026
+ const longRunningDirective = isBrightsy || isOrchestration ? null : formatLongRunningDirective();
24027
+ const optionalServicesDirective = isBrightsy || isOrchestration ? null : formatOptionalServicesDirective(loadAppSettings().integrations);
24028
+ const freshIssueTicket = issueTicketFromThread(fresh, resolveEffectiveIssueSource());
24029
+ const issueToolsDirective = isBrightsy || isOrchestration ? null : formatIssueToolsDirective({
24030
+ linear: isLinearConnected(),
24031
+ abletime: isAbleTimeConnected(),
24032
+ github: true,
24033
+ ticketId: freshIssueTicket?.id,
24034
+ ticketProvider: freshIssueTicket?.provider
24035
+ });
24036
+ const reviewWriteGateDirective = isBrightsy || isOrchestration || !isReviewWriteGatedThread(
24037
+ fresh,
24038
+ fresh.worktreePath ? threadsSharingWorktree(fresh.worktreePath) : []
24039
+ ) ? null : formatReviewWriteGateDirective();
24040
+ let viewerContextDirective = null;
24041
+ if (!isBrightsy && !isOrchestration) {
24042
+ try {
24043
+ viewerContextDirective = formatViewerContextDirective(
24044
+ resolveViewerProfileForRepo(fresh.repoPath || fresh.worktreePath)
24045
+ );
24046
+ } catch {
24047
+ viewerContextDirective = formatViewerContextDirective(
24048
+ resolveViewerProfileForRepo()
24049
+ );
24050
+ }
23882
24051
  }
23883
- if (!fresh.sessionId) {
23884
- const inventory = await enrichWorkspacesWithGithub(this.listWorkspaces());
23885
- coordinatorDirective = coordinatorSystemPrompt({
23886
- goal: fresh.sourceRef || fresh.title || "Orchestration",
23887
- parentId: fresh.id,
23888
- workspaces: inventory,
23889
- audience: /^(Slack DM|Slack @mention)(?:\n|$)/.test(
23890
- expandedPrompt.trim()
23891
- ) ? "slack" : "desktop"
24052
+ const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
24053
+ let renameBranchDirective = null;
24054
+ if (!isBrightsy && !isOrchestration && autoRenameBranchEnabled2()) {
24055
+ const { resolveGitBranchPrefix: resolveGitBranchPrefix2 } = await Promise.resolve().then(() => (init_branch_prefix(), branch_prefix_exports));
24056
+ renameBranchDirective = formatRenameBranchDirective(fresh, {
24057
+ customPrompt: settings?.prompts?.renameBranch,
24058
+ branchPrefix: resolveGitBranchPrefix2({
24059
+ setting: gitBranchPrefixSetting2()
24060
+ })
23892
24061
  });
23893
24062
  }
23894
- }
23895
- const cachedPrefix = fresh.sessionId ? "" : [
23896
- coordinatorDirective,
23897
- worktreeDirective,
23898
- optionalServicesDirective,
23899
- issueToolsDirective,
23900
- reviewWriteGateDirective,
23901
- viewerContextDirective,
23902
- artifactDirective,
23903
- longRunningDirective,
23904
- renameBranchDirective,
23905
- seed
23906
- ].filter(Boolean).join("\n\n---\n\n");
23907
- try {
24063
+ let seed = null;
24064
+ if (!fresh.sessionId) {
24065
+ const prior = fresh.messages.slice(0, -1);
24066
+ seed = isBrightsy ? buildBrightsySessionSeed(prior) : buildSessionSeed(prior);
24067
+ }
24068
+ let coordinatorDirective = null;
24069
+ if (isOrchestration) {
24070
+ if (isGlobalThread(fresh)) {
24071
+ ensureGlobalCoordinatorCwd({ orchestratorThreadId: fresh.id });
24072
+ }
24073
+ if (!fresh.sessionId) {
24074
+ const inventory = await enrichWorkspacesWithGithub(this.listWorkspaces());
24075
+ coordinatorDirective = coordinatorSystemPrompt({
24076
+ goal: fresh.sourceRef || fresh.title || "Orchestration",
24077
+ parentId: fresh.id,
24078
+ workspaces: inventory,
24079
+ audience: /^(Slack DM|Slack @mention)(?:\n|$)/.test(
24080
+ expandedPrompt.trim()
24081
+ ) ? "slack" : "desktop"
24082
+ });
24083
+ }
24084
+ }
24085
+ const cachedPrefix = fresh.sessionId ? "" : [
24086
+ coordinatorDirective,
24087
+ worktreeDirective,
24088
+ optionalServicesDirective,
24089
+ issueToolsDirective,
24090
+ reviewWriteGateDirective,
24091
+ viewerContextDirective,
24092
+ artifactDirective,
24093
+ longRunningDirective,
24094
+ renameBranchDirective,
24095
+ seed
24096
+ ].filter(Boolean).join("\n\n---\n\n");
23908
24097
  const stderrTail = [];
24098
+ traceTurn("runTurn.beforeSpawn", { threadId, agent: fresh.agent });
23909
24099
  const handle = await spawnAgentTurn(
23910
24100
  fresh,
23911
24101
  {
@@ -24705,6 +24895,18 @@ var init_orchestrator = __esm({
24705
24895
  const thread = this.requireThread(threadRef);
24706
24896
  return listWorktreeFiles(thread.worktreePath);
24707
24897
  }
24898
+ async statPath(threadRef, relativePath) {
24899
+ const thread = this.requireThread(threadRef);
24900
+ if (relativePath.includes("..") || relativePath.startsWith("/")) {
24901
+ return "missing";
24902
+ }
24903
+ if (!relativePath || relativePath === ".") return "dir";
24904
+ try {
24905
+ return statWorktreePath(thread.worktreePath, relativePath);
24906
+ } catch {
24907
+ return "missing";
24908
+ }
24909
+ }
24708
24910
  async readFile(threadRef, relativePath) {
24709
24911
  const thread = this.requireThread(threadRef);
24710
24912
  if (relativePath.includes("..") || relativePath.startsWith("/")) {
@@ -25187,7 +25389,7 @@ var init_orchestrator = __esm({
25187
25389
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
25188
25390
  return restored2;
25189
25391
  }
25190
- if (!(0, import_node_fs54.existsSync)(thread.worktreePath)) {
25392
+ if (!(0, import_node_fs55.existsSync)(thread.worktreePath)) {
25191
25393
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
25192
25394
  throw new Error(
25193
25395
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
@@ -25967,6 +26169,7 @@ __export(index_exports, {
25967
26169
  maxConcurrentAgents: () => maxConcurrentAgents,
25968
26170
  maybeCompactContext: () => maybeCompactContext,
25969
26171
  mcpAllowTools: () => mcpAllowTools,
26172
+ mcpAllowToolsFromNames: () => mcpAllowToolsFromNames,
25970
26173
  mcpAuthWarnings: () => mcpAuthWarnings,
25971
26174
  mcpStatusThinkingFromClaudeInit: () => mcpStatusThinkingFromClaudeInit,
25972
26175
  mentionsPrGoal: () => mentionsPrGoal,
@@ -26179,6 +26382,7 @@ __export(index_exports, {
26179
26382
  startOrchestration: () => startOrchestration,
26180
26383
  startSlackOAuth: () => startSlackOAuth,
26181
26384
  startSlackRelayServer: () => startSlackRelayServer,
26385
+ statWorktreePath: () => statWorktreePath,
26182
26386
  stripBrightsyNdjsonNoise: () => stripBrightsyNdjsonNoise,
26183
26387
  stripNestedElectronEnv: () => stripNestedElectronEnv,
26184
26388
  submitPrStack: () => submitPrStack,
@@ -28681,7 +28885,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
28681
28885
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
28682
28886
  var import_zod9 = require("zod");
28683
28887
  var import_node_crypto15 = require("crypto");
28684
- var import_node_path53 = require("path");
28888
+ var import_node_path55 = require("path");
28685
28889
  init_orchestrator();
28686
28890
  init_worktree();
28687
28891
  init_global_workspace();
@@ -30401,27 +30605,27 @@ init_gh_errors();
30401
30605
  init_git_auth_mode();
30402
30606
 
30403
30607
  // src/board/load-home-board.ts
30404
- var import_node_fs56 = require("fs");
30405
- var import_node_path52 = require("path");
30608
+ var import_node_fs57 = require("fs");
30609
+ var import_node_path54 = require("path");
30406
30610
  init_worktree();
30407
30611
  init_paths();
30408
30612
 
30409
30613
  // src/board/board-pins.ts
30410
30614
  var import_node_crypto14 = require("crypto");
30411
- var import_node_fs55 = require("fs");
30412
- var import_node_path51 = require("path");
30615
+ var import_node_fs56 = require("fs");
30616
+ var import_node_path53 = require("path");
30413
30617
  init_paths();
30414
30618
  init_home_board();
30415
30619
  var FILE = "home-board-pins.json";
30416
30620
  var VERSION = 1;
30417
30621
  function pinsFile() {
30418
- return (0, import_node_path51.join)(appDataDir(), FILE);
30622
+ return (0, import_node_path53.join)(appDataDir(), FILE);
30419
30623
  }
30420
30624
  function readDisk() {
30421
30625
  const path2 = pinsFile();
30422
- if (!(0, import_node_fs55.existsSync)(path2)) return [];
30626
+ if (!(0, import_node_fs56.existsSync)(path2)) return [];
30423
30627
  try {
30424
- const raw = JSON.parse((0, import_node_fs55.readFileSync)(path2, "utf8"));
30628
+ const raw = JSON.parse((0, import_node_fs56.readFileSync)(path2, "utf8"));
30425
30629
  if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
30426
30630
  return raw.items.filter((item) => item?.id && item.kind && item.ref);
30427
30631
  } catch {
@@ -30429,8 +30633,8 @@ function readDisk() {
30429
30633
  }
30430
30634
  }
30431
30635
  function writeDisk(items) {
30432
- (0, import_node_fs55.mkdirSync)(appDataDir(), { recursive: true });
30433
- (0, import_node_fs55.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
30636
+ (0, import_node_fs56.mkdirSync)(appDataDir(), { recursive: true });
30637
+ (0, import_node_fs56.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
30434
30638
  }
30435
30639
  function listBoardPins() {
30436
30640
  return readDisk();
@@ -30482,7 +30686,7 @@ function replaceBoardPins(items) {
30482
30686
  }
30483
30687
  function clearBoardPins() {
30484
30688
  try {
30485
- (0, import_node_fs55.unlinkSync)(pinsFile());
30689
+ (0, import_node_fs56.unlinkSync)(pinsFile());
30486
30690
  } catch {
30487
30691
  }
30488
30692
  }
@@ -30499,7 +30703,7 @@ function homeBoardWorkspaceKey(workspaces) {
30499
30703
  return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
30500
30704
  }
30501
30705
  function cacheFile() {
30502
- return (0, import_node_path52.join)(appDataDir(), "home-board-cache.json");
30706
+ return (0, import_node_path54.join)(appDataDir(), "home-board-cache.json");
30503
30707
  }
30504
30708
  function emptyInputs() {
30505
30709
  return {
@@ -30525,9 +30729,9 @@ function shouldCacheHomeBoardInputs(inputs) {
30525
30729
  }
30526
30730
  function readDiskCache() {
30527
30731
  const path2 = cacheFile();
30528
- if (!(0, import_node_fs56.existsSync)(path2)) return null;
30732
+ if (!(0, import_node_fs57.existsSync)(path2)) return null;
30529
30733
  try {
30530
- const raw = JSON.parse((0, import_node_fs56.readFileSync)(path2, "utf8"));
30734
+ const raw = JSON.parse((0, import_node_fs57.readFileSync)(path2, "utf8"));
30531
30735
  if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
30532
30736
  return null;
30533
30737
  }
@@ -30541,14 +30745,14 @@ function readDiskCache() {
30541
30745
  }
30542
30746
  function writeDiskCache(entry) {
30543
30747
  try {
30544
- (0, import_node_fs56.mkdirSync)(appDataDir(), { recursive: true });
30545
- (0, import_node_fs56.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
30748
+ (0, import_node_fs57.mkdirSync)(appDataDir(), { recursive: true });
30749
+ (0, import_node_fs57.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
30546
30750
  } catch {
30547
30751
  }
30548
30752
  }
30549
30753
  function deleteDiskCache() {
30550
30754
  try {
30551
- (0, import_node_fs56.unlinkSync)(cacheFile());
30755
+ (0, import_node_fs57.unlinkSync)(cacheFile());
30552
30756
  } catch {
30553
30757
  }
30554
30758
  }
@@ -30734,7 +30938,7 @@ function orchCreateThreadAgentNote(input) {
30734
30938
  // src/mcp/server.ts
30735
30939
  var MAX_ORCH_THREADS = 5;
30736
30940
  var CREATE_THREAD_TIMEOUT_MS = 9e4;
30737
- function withTimeout(promise, ms, label) {
30941
+ function withTimeout2(promise, ms, label) {
30738
30942
  return new Promise((resolve, reject) => {
30739
30943
  const timer = setTimeout(() => {
30740
30944
  reject(new Error(`${label} timed out after ${Math.round(ms / 1e3)}s`));
@@ -30788,7 +30992,7 @@ async function createOrchChildThread(orch, args, resolveNewThreadOptions2) {
30788
30992
  const agentNote = orchCreateThreadAgentNote(opts);
30789
30993
  try {
30790
30994
  const priorIds = new Set(orch.getThreads(false).map((t) => t.id));
30791
- const thread = await withTimeout(
30995
+ const thread = await withTimeout2(
30792
30996
  orch.createThread({
30793
30997
  sourceType: args.sourceType,
30794
30998
  sourceRef: args.sourceRef,
@@ -30898,7 +31102,7 @@ async function startMcpServer() {
30898
31102
  async () => {
30899
31103
  const threads = orch.getThreads(true);
30900
31104
  const lines = threads.map((t) => {
30901
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID2 ? "Orchestration" : (0, import_node_path53.basename)(t.repoPath) || t.repoPath;
31105
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID2 ? "Orchestration" : (0, import_node_path55.basename)(t.repoPath) || t.repoPath;
30902
31106
  const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
30903
31107
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
30904
31108
  const preview = lastMessagePreview(t.messages, 80);
@@ -33865,9 +34069,9 @@ var import_node_http4 = require("http");
33865
34069
  var import_ws3 = require("ws");
33866
34070
 
33867
34071
  // src/slack/relay-static.ts
33868
- var import_node_fs57 = require("fs");
34072
+ var import_node_fs58 = require("fs");
33869
34073
  var import_promises = require("fs/promises");
33870
- var import_node_path54 = __toESM(require("path"), 1);
34074
+ var import_node_path56 = __toESM(require("path"), 1);
33871
34075
  var TYPES = {
33872
34076
  ".css": "text/css; charset=utf-8",
33873
34077
  ".html": "text/html; charset=utf-8",
@@ -33898,9 +34102,9 @@ function resolveStaticPath(root, requestUrl) {
33898
34102
  return null;
33899
34103
  }
33900
34104
  if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
33901
- const rootResolved = import_node_path54.default.resolve(root);
33902
- const candidate = import_node_path54.default.resolve(rootResolved, `.${pathname}`);
33903
- if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path54.default.sep)) {
34105
+ const rootResolved = import_node_path56.default.resolve(root);
34106
+ const candidate = import_node_path56.default.resolve(rootResolved, `.${pathname}`);
34107
+ if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path56.default.sep)) {
33904
34108
  return null;
33905
34109
  }
33906
34110
  return candidate;
@@ -33914,7 +34118,7 @@ async function fileSize(file) {
33914
34118
  }
33915
34119
  }
33916
34120
  function sendFile(req, res, file, size) {
33917
- const ext = import_node_path54.default.extname(file).toLowerCase();
34121
+ const ext = import_node_path56.default.extname(file).toLowerCase();
33918
34122
  res.writeHead(200, {
33919
34123
  "Content-Type": TYPES[ext] ?? "application/octet-stream",
33920
34124
  "Content-Length": size,
@@ -33924,7 +34128,7 @@ function sendFile(req, res, file, size) {
33924
34128
  res.end();
33925
34129
  return true;
33926
34130
  }
33927
- (0, import_node_fs57.createReadStream)(file).pipe(res);
34131
+ (0, import_node_fs58.createReadStream)(file).pipe(res);
33928
34132
  return true;
33929
34133
  }
33930
34134
  async function tryServeStatic(req, res, root) {
@@ -33933,7 +34137,7 @@ async function tryServeStatic(req, res, root) {
33933
34137
  if (!candidate) return false;
33934
34138
  const direct = await fileSize(candidate);
33935
34139
  if (direct != null) return sendFile(req, res, candidate, direct);
33936
- const asIndex = import_node_path54.default.join(candidate, "index.html");
34140
+ const asIndex = import_node_path56.default.join(candidate, "index.html");
33937
34141
  const indexSize = await fileSize(asIndex);
33938
34142
  if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
33939
34143
  return false;
@@ -34756,6 +34960,7 @@ init_outbound_watch();
34756
34960
  maxConcurrentAgents,
34757
34961
  maybeCompactContext,
34758
34962
  mcpAllowTools,
34963
+ mcpAllowToolsFromNames,
34759
34964
  mcpAuthWarnings,
34760
34965
  mcpStatusThinkingFromClaudeInit,
34761
34966
  mentionsPrGoal,
@@ -34968,6 +35173,7 @@ init_outbound_watch();
34968
35173
  startOrchestration,
34969
35174
  startSlackOAuth,
34970
35175
  startSlackRelayServer,
35176
+ statWorktreePath,
34971
35177
  stripBrightsyNdjsonNoise,
34972
35178
  stripNestedElectronEnv,
34973
35179
  submitPrStack,