@sideboard-ai/core 0.1.174 → 0.1.176

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 (40) hide show
  1. package/dist/{abletime-PCLL36HW.js → abletime-BFIDZR3O.js} +2 -2
  2. package/dist/{abletime-7VW4EGPT.js → abletime-INEHQH6K.js} +2 -2
  3. package/dist/agents/cursor-runner.cjs +91 -62
  4. package/dist/agents/cursor-runner.js +1 -1
  5. package/dist/{agents-ZWYRGFZB.js → agents-544IX5KA.js} +8 -6
  6. package/dist/{agents-LMPVUPOH.js → agents-UENEQ6J2.js} +7 -5
  7. package/dist/{chunk-ZY7K4T37.js → chunk-3ZFGZ7RT.js} +5 -5
  8. package/dist/{chunk-HJPGIETB.js → chunk-4ELBAYFW.js} +19 -14
  9. package/dist/{chunk-M267JPEA.js → chunk-AN3THU7F.js} +1 -1
  10. package/dist/{chunk-AQPVBVJE.js → chunk-BBNUL4IE.js} +1 -1
  11. package/dist/{chunk-VCVBICMZ.js → chunk-FJWQCZ74.js} +5 -5
  12. package/dist/{chunk-LZ6QMEQC.js → chunk-HVIEYTUK.js} +1 -1
  13. package/dist/{chunk-XD2BAANL.js → chunk-IEEAVWAP.js} +6 -6
  14. package/dist/{chunk-YEPVWJ3R.js → chunk-JUA7XEXR.js} +16 -11
  15. package/dist/{chunk-ELBYOGVA.js → chunk-N7WZ6NIN.js} +10 -1
  16. package/dist/{chunk-CUA4S537.js → chunk-NIB6BTC6.js} +9 -5
  17. package/dist/{chunk-XXIH6XYR.js → chunk-NQTKRAUF.js} +167 -35
  18. package/dist/{chunk-CMJ2FBBV.js → chunk-RE2YWFUQ.js} +1 -1
  19. package/dist/{chunk-6GN5WPYZ.js → chunk-VKQGAWHY.js} +10 -1
  20. package/dist/{chunk-TPPZXZTA.js → chunk-W44EKPIR.js} +228 -95
  21. package/dist/{chunk-S42XV45P.js → chunk-Y4MIXGPA.js} +1 -1
  22. package/dist/{connected-teams-DBWAMP7G.js → connected-teams-ON2KIKQX.js} +3 -3
  23. package/dist/{connected-teams-WGONUQOF.js → connected-teams-WOYCH7FR.js} +3 -3
  24. package/dist/{coordinator-prompt-K3HXEPFD.js → coordinator-prompt-BE2FERYE.js} +1 -1
  25. package/dist/{coordinator-prompt-LJKA2ODR.js → coordinator-prompt-PRM5ARWG.js} +1 -1
  26. package/dist/{global-workspace-VDFSU3DD.js → global-workspace-3HIWNQ3B.js} +1 -1
  27. package/dist/{global-workspace-KA7T26F5.js → global-workspace-J737XNUX.js} +1 -1
  28. package/dist/index.cjs +584 -379
  29. package/dist/index.d.cts +53 -10
  30. package/dist/index.d.ts +53 -10
  31. package/dist/index.js +76 -27
  32. package/dist/mcp/run-stdio.cjs +778 -576
  33. package/dist/mcp/run-stdio.js +78 -27
  34. package/dist/{oauth-A7XXI2TM.js → oauth-6ZQ4Q4XN.js} +2 -2
  35. package/dist/{oauth-YJBAURIJ.js → oauth-O7UGLZOY.js} +2 -2
  36. package/dist/{orchestrator-DMSSC4SV.js → orchestrator-2KZD7N4X.js} +6 -6
  37. package/dist/{orchestrator-VMUZJFTZ.js → orchestrator-GDKEVLFK.js} +7 -7
  38. package/dist/{workspaces-GOGBPATJ.js → workspaces-DR4UNOQC.js} +1 -1
  39. package/dist/{workspaces-UR7YEFMZ.js → workspaces-ULHYXM4Y.js} +1 -1
  40. package/package.json +1 -1
@@ -491,24 +491,156 @@ var init_paths = __esm({
491
491
  }
492
492
  });
493
493
 
494
+ // src/http/system-ca.ts
495
+ function splitPemCertificates(pem) {
496
+ return pem.match(PEM_CERT_RE) ?? [];
497
+ }
498
+ function readExistingFile(path) {
499
+ try {
500
+ return (0, import_node_fs5.existsSync)(path) ? (0, import_node_fs5.readFileSync)(path, "utf8") : "";
501
+ } catch {
502
+ return "";
503
+ }
504
+ }
505
+ function darwinKeychainPem(spawn2) {
506
+ const result = spawn2("/usr/bin/security", ["find-certificate", "-a", "-p"], {
507
+ encoding: "utf8",
508
+ maxBuffer: 32 * 1024 * 1024,
509
+ timeout: 15e3
510
+ });
511
+ if (result.status !== 0) return "";
512
+ return typeof result.stdout === "string" ? result.stdout : "";
513
+ }
514
+ function linuxSystemCaPem() {
515
+ for (const path of LINUX_CA_FILES) {
516
+ const pem = readExistingFile(path);
517
+ if (splitPemCertificates(pem).length > 0) return pem;
518
+ }
519
+ return "";
520
+ }
521
+ function collectSystemCaPem(io = {}) {
522
+ const platform = io.platform ?? process.platform;
523
+ if (platform === "darwin") {
524
+ return darwinKeychainPem(io.spawn ?? import_node_child_process.spawnSync);
525
+ }
526
+ if (platform === "linux") {
527
+ return linuxSystemCaPem();
528
+ }
529
+ return "";
530
+ }
531
+ function systemCaBundlePath(io = {}) {
532
+ return (0, import_node_path6.join)((io.appData ?? appDataDir)(), BUNDLE_NAME);
533
+ }
534
+ function bundleIsFresh(path, now) {
535
+ try {
536
+ if (!(0, import_node_fs5.existsSync)(path)) return false;
537
+ if (splitPemCertificates((0, import_node_fs5.readFileSync)(path, "utf8")).length === 0) return false;
538
+ return now - (0, import_node_fs5.statSync)(path).mtimeMs < BUNDLE_MAX_AGE_MS;
539
+ } catch {
540
+ return false;
541
+ }
542
+ }
543
+ function materializeSystemCaBundle(io = {}) {
544
+ const inherited = process.env.NODE_EXTRA_CA_CERTS?.trim();
545
+ if (inherited && splitPemCertificates(readExistingFile(inherited)).length > 0) {
546
+ return inherited;
547
+ }
548
+ const platform = io.platform ?? process.platform;
549
+ if (platform === "linux") {
550
+ for (const path of LINUX_CA_FILES) {
551
+ if (splitPemCertificates(readExistingFile(path)).length > 0) return path;
552
+ }
553
+ }
554
+ const dest = systemCaBundlePath(io);
555
+ const now = (io.now ?? Date.now)();
556
+ if (bundleIsFresh(dest, now)) return dest;
557
+ const pem = collectSystemCaPem(io);
558
+ if (splitPemCertificates(pem).length === 0) {
559
+ return (0, import_node_fs5.existsSync)(dest) && splitPemCertificates(readExistingFile(dest)).length > 0 ? dest : void 0;
560
+ }
561
+ try {
562
+ (0, import_node_fs5.mkdirSync)((0, import_node_path6.dirname)(dest), { recursive: true });
563
+ (0, import_node_fs5.writeFileSync)(dest, pem.endsWith("\n") ? pem : `${pem}
564
+ `, { mode: 384 });
565
+ return dest;
566
+ } catch {
567
+ return void 0;
568
+ }
569
+ }
570
+ function applySystemCaEnv(env) {
571
+ if (!String(env[NODE_USE_SYSTEM_CA] ?? "").trim()) {
572
+ env[NODE_USE_SYSTEM_CA] = "1";
573
+ }
574
+ if (String(env[NODE_EXTRA_CA_CERTS] ?? "").trim()) return;
575
+ const inherited = process.env.NODE_EXTRA_CA_CERTS?.trim();
576
+ if (inherited) env[NODE_EXTRA_CA_CERTS] = inherited;
577
+ }
578
+ function extraCertsFromBundle() {
579
+ const path = process.env.NODE_EXTRA_CA_CERTS?.trim();
580
+ if (path) return splitPemCertificates(readExistingFile(path));
581
+ const dest = systemCaBundlePath();
582
+ return splitPemCertificates(readExistingFile(dest));
583
+ }
584
+ function trustSystemCertificates(io = {}) {
585
+ try {
586
+ const api = import_node_tls.default;
587
+ if (typeof api.getCACertificates !== "function" || typeof api.setDefaultCACertificates !== "function") {
588
+ return false;
589
+ }
590
+ const current = api.getCACertificates("default");
591
+ const system = api.getCACertificates("system");
592
+ let extra = extraCertsFromBundle();
593
+ if (system.length === 0 && extra.length === 0) {
594
+ extra = splitPemCertificates(collectSystemCaPem(io));
595
+ }
596
+ if (system.length === 0 && extra.length === 0) return false;
597
+ api.setDefaultCACertificates([...current, ...system, ...extra]);
598
+ return true;
599
+ } catch {
600
+ return false;
601
+ }
602
+ }
603
+ var import_node_child_process, import_node_fs5, import_node_path6, import_node_tls, NODE_USE_SYSTEM_CA, NODE_EXTRA_CA_CERTS, BUNDLE_NAME, BUNDLE_MAX_AGE_MS, LINUX_CA_FILES, PEM_CERT_RE;
604
+ var init_system_ca = __esm({
605
+ "src/http/system-ca.ts"() {
606
+ "use strict";
607
+ import_node_child_process = require("child_process");
608
+ import_node_fs5 = require("fs");
609
+ import_node_path6 = require("path");
610
+ import_node_tls = __toESM(require("tls"), 1);
611
+ init_paths();
612
+ NODE_USE_SYSTEM_CA = "NODE_USE_SYSTEM_CA";
613
+ NODE_EXTRA_CA_CERTS = "NODE_EXTRA_CA_CERTS";
614
+ BUNDLE_NAME = "system-ca.pem";
615
+ BUNDLE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
616
+ LINUX_CA_FILES = [
617
+ "/etc/ssl/certs/ca-certificates.crt",
618
+ "/etc/pki/tls/certs/ca-bundle.crt",
619
+ "/etc/ssl/ca-bundle.pem",
620
+ "/etc/ssl/cert.pem"
621
+ ];
622
+ PEM_CERT_RE = /-----BEGIN CERTIFICATE-----[\s\S]*?-----END CERTIFICATE-----/g;
623
+ }
624
+ });
625
+
494
626
  // src/store/private-file.ts
495
627
  function writePrivateFile(path, contents) {
496
- (0, import_node_fs5.mkdirSync)((0, import_node_path6.dirname)(path), { recursive: true });
497
- (0, import_node_fs5.writeFileSync)(path, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
628
+ (0, import_node_fs6.mkdirSync)((0, import_node_path7.dirname)(path), { recursive: true });
629
+ (0, import_node_fs6.writeFileSync)(path, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
498
630
  chmodOwnerOnly(path);
499
631
  }
500
632
  function chmodOwnerOnly(path) {
501
633
  try {
502
- (0, import_node_fs5.chmodSync)(path, PRIVATE_FILE_MODE);
634
+ (0, import_node_fs6.chmodSync)(path, PRIVATE_FILE_MODE);
503
635
  } catch {
504
636
  }
505
637
  }
506
- var import_node_fs5, import_node_path6, PRIVATE_FILE_MODE;
638
+ var import_node_fs6, import_node_path7, PRIVATE_FILE_MODE;
507
639
  var init_private_file = __esm({
508
640
  "src/store/private-file.ts"() {
509
641
  "use strict";
510
- import_node_fs5 = require("fs");
511
- import_node_path6 = require("path");
642
+ import_node_fs6 = require("fs");
643
+ import_node_path7 = require("path");
512
644
  PRIVATE_FILE_MODE = 384;
513
645
  }
514
646
  });
@@ -517,7 +649,7 @@ var init_private_file = __esm({
517
649
  function persistVaultKeyInKeychain(key) {
518
650
  if (process.platform !== "darwin" || key.length !== 32) return;
519
651
  try {
520
- (0, import_node_child_process.execFileSync)(
652
+ (0, import_node_child_process2.execFileSync)(
521
653
  "security",
522
654
  [
523
655
  "add-generic-password",
@@ -542,7 +674,7 @@ function hexKey(value) {
542
674
  function keychainKey(create) {
543
675
  if (process.platform !== "darwin") return null;
544
676
  try {
545
- const out = (0, import_node_child_process.execFileSync)(
677
+ const out = (0, import_node_child_process2.execFileSync)(
546
678
  "security",
547
679
  ["find-generic-password", "-s", KEYCHAIN_SERVICE, "-a", KEYCHAIN_ACCOUNT, "-w"],
548
680
  { encoding: "utf8", timeout: 5e3, stdio: ["ignore", "pipe", "pipe"] }
@@ -594,11 +726,11 @@ function decryptEnvelope(envelope, key) {
594
726
  return JSON.parse(plaintext.toString("utf8"));
595
727
  }
596
728
  function readSecureJson(path) {
597
- if (!(0, import_node_fs6.existsSync)(path)) return null;
729
+ if (!(0, import_node_fs7.existsSync)(path)) return null;
598
730
  chmodOwnerOnly(path);
599
731
  let parsed;
600
732
  try {
601
- parsed = JSON.parse((0, import_node_fs6.readFileSync)(path, "utf8"));
733
+ parsed = JSON.parse((0, import_node_fs7.readFileSync)(path, "utf8"));
602
734
  } catch {
603
735
  return null;
604
736
  }
@@ -618,20 +750,20 @@ function writeSecureJson(path, value) {
618
750
  `);
619
751
  }
620
752
  function isSecureFileEncrypted(path) {
621
- if (!(0, import_node_fs6.existsSync)(path)) return false;
753
+ if (!(0, import_node_fs7.existsSync)(path)) return false;
622
754
  try {
623
- return isEnvelope(JSON.parse((0, import_node_fs6.readFileSync)(path, "utf8")));
755
+ return isEnvelope(JSON.parse((0, import_node_fs7.readFileSync)(path, "utf8")));
624
756
  } catch {
625
757
  return false;
626
758
  }
627
759
  }
628
- var import_node_child_process, import_node_crypto, import_node_fs6, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, ALG, injectedKey;
760
+ var import_node_child_process2, import_node_crypto, import_node_fs7, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, ALG, injectedKey;
629
761
  var init_secure_file = __esm({
630
762
  "src/store/secure-file.ts"() {
631
763
  "use strict";
632
- import_node_child_process = require("child_process");
764
+ import_node_child_process2 = require("child_process");
633
765
  import_node_crypto = require("crypto");
634
- import_node_fs6 = require("fs");
766
+ import_node_fs7 = require("fs");
635
767
  init_private_file();
636
768
  KEYCHAIN_SERVICE = "ai.sideboard.app";
637
769
  KEYCHAIN_ACCOUNT = "secret-vault-v1";
@@ -756,7 +888,7 @@ function createEmptyThread(partial) {
756
888
  }
757
889
  async function withThreadLock(id, fn) {
758
890
  const lockPath = threadLockPath(id);
759
- (0, import_node_fs7.writeFileSync)(lockPath, "", { flag: "a" });
891
+ (0, import_node_fs8.writeFileSync)(lockPath, "", { flag: "a" });
760
892
  let release;
761
893
  try {
762
894
  release = await import_proper_lockfile.default.lock(lockPath, {
@@ -777,7 +909,7 @@ function cacheForDir() {
777
909
  }
778
910
  function fileMtimeMs(path) {
779
911
  try {
780
- return (0, import_node_fs7.statSync)(path).mtimeMs;
912
+ return (0, import_node_fs8.statSync)(path).mtimeMs;
781
913
  } catch {
782
914
  return null;
783
915
  }
@@ -805,7 +937,7 @@ function readThread(id) {
805
937
  const cache = cacheForDir();
806
938
  const cached = cache.byId.get(id);
807
939
  if (cached && cache.mtimeMs.get(id) === mtimeMs) return cached;
808
- const raw = (0, import_node_fs7.readFileSync)(path, "utf8");
940
+ const raw = (0, import_node_fs8.readFileSync)(path, "utf8");
809
941
  const thread = normalizeThread(JSON.parse(raw));
810
942
  rememberThread(thread, mtimeMs);
811
943
  return thread;
@@ -814,20 +946,20 @@ function writeThread(thread) {
814
946
  const path = threadFilePath(idPath(thread.id));
815
947
  const tmp = `${path}.${process.pid}.tmp`;
816
948
  const next = { ...thread, updatedAt: nowIso() };
817
- (0, import_node_fs7.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
818
- (0, import_node_fs7.renameSync)(tmp, path);
949
+ (0, import_node_fs8.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
950
+ (0, import_node_fs8.renameSync)(tmp, path);
819
951
  rememberThread(next, fileMtimeMs(path) ?? Date.now());
820
952
  }
821
953
  function idPath(id) {
822
954
  return id;
823
955
  }
824
956
  function isThreadRecordFile(nameOrPath) {
825
- const name = (0, import_node_path7.basename)(nameOrPath);
957
+ const name = (0, import_node_path8.basename)(nameOrPath);
826
958
  return name.endsWith(".json") && !name.endsWith(".live.json");
827
959
  }
828
960
  function listThreads(opts) {
829
961
  const cache = cacheForDir();
830
- const files = (0, import_node_fs7.readdirSync)(threadsDir()).filter(isThreadRecordFile);
962
+ const files = (0, import_node_fs8.readdirSync)(threadsDir()).filter(isThreadRecordFile);
831
963
  const seen = /* @__PURE__ */ new Set();
832
964
  for (const f of files) {
833
965
  const id = f.replace(/\.json$/, "");
@@ -850,11 +982,11 @@ function listThreads(opts) {
850
982
  function deleteThreadRecord(id) {
851
983
  forgetThread(id);
852
984
  const path = threadFilePath(id);
853
- if ((0, import_node_fs7.existsSync)(path)) (0, import_node_fs7.unlinkSync)(path);
985
+ if ((0, import_node_fs8.existsSync)(path)) (0, import_node_fs8.unlinkSync)(path);
854
986
  const lock = threadLockPath(id);
855
- if ((0, import_node_fs7.existsSync)(lock)) {
987
+ if ((0, import_node_fs8.existsSync)(lock)) {
856
988
  try {
857
- (0, import_node_fs7.unlinkSync)(lock);
989
+ (0, import_node_fs8.unlinkSync)(lock);
858
990
  } catch {
859
991
  }
860
992
  }
@@ -880,13 +1012,13 @@ function findThreadByRef(ref) {
880
1012
  (t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref
881
1013
  ) ?? null;
882
1014
  }
883
- var import_node_crypto2, import_node_fs7, import_node_path7, import_proper_lockfile, listCache;
1015
+ var import_node_crypto2, import_node_fs8, import_node_path8, import_proper_lockfile, listCache;
884
1016
  var init_thread_store = __esm({
885
1017
  "src/store/thread-store.ts"() {
886
1018
  "use strict";
887
1019
  import_node_crypto2 = require("crypto");
888
- import_node_fs7 = require("fs");
889
- import_node_path7 = require("path");
1020
+ import_node_fs8 = require("fs");
1021
+ import_node_path8 = require("path");
890
1022
  import_proper_lockfile = __toESM(require("proper-lockfile"), 1);
891
1023
  init_thinking_effort();
892
1024
  init_paths();
@@ -938,13 +1070,13 @@ var init_api = __esm({
938
1070
 
939
1071
  // src/slack/reply-target.ts
940
1072
  function storePath() {
941
- return (0, import_node_path8.join)(appDataDir(), "slack-reply-to.json");
1073
+ return (0, import_node_path9.join)(appDataDir(), "slack-reply-to.json");
942
1074
  }
943
1075
  function readStore() {
944
1076
  const path = storePath();
945
- if (!(0, import_node_fs8.existsSync)(path)) return {};
1077
+ if (!(0, import_node_fs9.existsSync)(path)) return {};
946
1078
  try {
947
- const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs8.readFileSync)(path, "utf8"));
1079
+ const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
948
1080
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
949
1081
  } catch {
950
1082
  return {};
@@ -953,12 +1085,12 @@ function readStore() {
953
1085
  function getSlackReplyTarget(threadId) {
954
1086
  return readStore()[threadId] ?? null;
955
1087
  }
956
- var import_node_fs8, import_node_path8;
1088
+ var import_node_fs9, import_node_path9;
957
1089
  var init_reply_target = __esm({
958
1090
  "src/slack/reply-target.ts"() {
959
1091
  "use strict";
960
- import_node_fs8 = require("fs");
961
- import_node_path8 = require("path");
1092
+ import_node_fs9 = require("fs");
1093
+ import_node_path9 = require("path");
962
1094
  init_paths();
963
1095
  init_private_file();
964
1096
  init_secure_file();
@@ -967,7 +1099,7 @@ var init_reply_target = __esm({
967
1099
 
968
1100
  // src/slack/workspaces.ts
969
1101
  function storePath2() {
970
- return (0, import_node_path9.join)(appDataDir(), "slack-workspaces.json");
1102
+ return (0, import_node_path10.join)(appDataDir(), "slack-workspaces.json");
971
1103
  }
972
1104
  function readStore2() {
973
1105
  try {
@@ -1028,11 +1160,11 @@ function requireSlackWorkspace(teamId) {
1028
1160
  }
1029
1161
  return ws;
1030
1162
  }
1031
- var import_node_path9;
1163
+ var import_node_path10;
1032
1164
  var init_workspaces = __esm({
1033
1165
  "src/slack/workspaces.ts"() {
1034
1166
  "use strict";
1035
- import_node_path9 = require("path");
1167
+ import_node_path10 = require("path");
1036
1168
  init_paths();
1037
1169
  init_secure_file();
1038
1170
  init_api();
@@ -1041,7 +1173,7 @@ var init_workspaces = __esm({
1041
1173
 
1042
1174
  // src/slack/outbound-watch.ts
1043
1175
  function storePath3() {
1044
- return (0, import_node_path10.join)(appDataDir(), "slack-outbound-watch.json");
1176
+ return (0, import_node_path11.join)(appDataDir(), "slack-outbound-watch.json");
1045
1177
  }
1046
1178
  function watchId(teamId, channelId, ts) {
1047
1179
  return `${teamId}:${channelId}:${ts}`;
@@ -1054,9 +1186,9 @@ function tsNewer(a, b) {
1054
1186
  }
1055
1187
  function readStore3() {
1056
1188
  const path = storePath3();
1057
- if (!(0, import_node_fs9.existsSync)(path)) return [];
1189
+ if (!(0, import_node_fs10.existsSync)(path)) return [];
1058
1190
  try {
1059
- const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs9.readFileSync)(path, "utf8"));
1191
+ const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs10.readFileSync)(path, "utf8"));
1060
1192
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
1061
1193
  } catch {
1062
1194
  return [];
@@ -1378,12 +1510,12 @@ async function pollSlackOutboundWatches(opts) {
1378
1510
  }
1379
1511
  if (changed) writeStore(watches);
1380
1512
  }
1381
- var import_node_fs9, import_node_path10, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
1513
+ var import_node_fs10, import_node_path11, MAX_WATCHES, MAX_REPLIES_PER_WATCH, WATCH_TTL_MS, POLL_INTERVAL_MS, lastPollMs, nameCache, continueOnReply;
1382
1514
  var init_outbound_watch = __esm({
1383
1515
  "src/slack/outbound-watch.ts"() {
1384
1516
  "use strict";
1385
- import_node_fs9 = require("fs");
1386
- import_node_path10 = require("path");
1517
+ import_node_fs10 = require("fs");
1518
+ import_node_path11 = require("path");
1387
1519
  init_paths();
1388
1520
  init_private_file();
1389
1521
  init_secure_file();
@@ -1703,64 +1835,64 @@ var init_error_detail = __esm({
1703
1835
 
1704
1836
  // src/agents/path.ts
1705
1837
  function prependPathDir(env, dir) {
1706
- if (!dir || !(0, import_node_fs10.existsSync)(dir)) return;
1838
+ if (!dir || !(0, import_node_fs11.existsSync)(dir)) return;
1707
1839
  const current = env.PATH ?? "";
1708
- const parts = current.split(import_node_path11.delimiter).filter(Boolean);
1840
+ const parts = current.split(import_node_path12.delimiter).filter(Boolean);
1709
1841
  if (parts.includes(dir)) {
1710
1842
  env.PATH = current;
1711
1843
  return;
1712
1844
  }
1713
- env.PATH = [dir, ...parts].join(import_node_path11.delimiter);
1845
+ env.PATH = [dir, ...parts].join(import_node_path12.delimiter);
1714
1846
  }
1715
1847
  function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os3.homedir)()) {
1716
- return (0, import_node_path11.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
1848
+ return (0, import_node_path12.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
1717
1849
  }
1718
1850
  function ensureAgentPath(env = process.env) {
1719
1851
  const home = env.HOME || env.USERPROFILE || (0, import_node_os3.homedir)();
1720
1852
  const current = env.PATH ?? "";
1721
- const parts = current.split(import_node_path11.delimiter).filter(Boolean);
1853
+ const parts = current.split(import_node_path12.delimiter).filter(Boolean);
1722
1854
  const seen = new Set(parts);
1723
1855
  const extras = [
1724
- ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path11.join)(home, rel)),
1856
+ ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path12.join)(home, rel)),
1725
1857
  "/opt/homebrew/bin",
1726
1858
  "/usr/local/bin",
1727
1859
  // Keep after Homebrew/npm so a user-installed CLI still wins.
1728
1860
  conductorBundledBinDir(home)
1729
1861
  ];
1730
1862
  for (const dir of extras.reverse()) {
1731
- if (!dir || seen.has(dir) || !(0, import_node_fs10.existsSync)(dir)) continue;
1863
+ if (!dir || seen.has(dir) || !(0, import_node_fs11.existsSync)(dir)) continue;
1732
1864
  parts.unshift(dir);
1733
1865
  seen.add(dir);
1734
1866
  }
1735
- const next = parts.join(import_node_path11.delimiter);
1867
+ const next = parts.join(import_node_path12.delimiter);
1736
1868
  env.PATH = next;
1737
1869
  return next;
1738
1870
  }
1739
1871
  function enrichPathWithNpmGlobalBin(env = process.env) {
1740
1872
  ensureAgentPath(env);
1741
1873
  try {
1742
- const prefix = (0, import_node_child_process2.execFileSync)("npm", ["prefix", "-g"], {
1874
+ const prefix = (0, import_node_child_process3.execFileSync)("npm", ["prefix", "-g"], {
1743
1875
  encoding: "utf8",
1744
1876
  env: { ...process.env, ...env },
1745
1877
  timeout: 8e3,
1746
1878
  stdio: ["ignore", "pipe", "ignore"]
1747
1879
  }).trim().split(/\r?\n/).find(Boolean);
1748
1880
  if (prefix) {
1749
- const binDir = process.platform === "win32" ? prefix : (0, import_node_path11.join)(prefix, "bin");
1881
+ const binDir = process.platform === "win32" ? prefix : (0, import_node_path12.join)(prefix, "bin");
1750
1882
  prependPathDir(env, binDir);
1751
1883
  }
1752
1884
  } catch {
1753
1885
  }
1754
1886
  return env.PATH ?? "";
1755
1887
  }
1756
- var import_node_fs10, import_node_child_process2, import_node_os3, import_node_path11, EXTRA_BIN_DIRS;
1888
+ var import_node_fs11, import_node_child_process3, import_node_os3, import_node_path12, EXTRA_BIN_DIRS;
1757
1889
  var init_path = __esm({
1758
1890
  "src/agents/path.ts"() {
1759
1891
  "use strict";
1760
- import_node_fs10 = require("fs");
1761
- import_node_child_process2 = require("child_process");
1892
+ import_node_fs11 = require("fs");
1893
+ import_node_child_process3 = require("child_process");
1762
1894
  import_node_os3 = require("os");
1763
- import_node_path11 = require("path");
1895
+ import_node_path12 = require("path");
1764
1896
  EXTRA_BIN_DIRS = [
1765
1897
  ".local/bin",
1766
1898
  ".cargo/bin",
@@ -1781,23 +1913,23 @@ var init_path = __esm({
1781
1913
  function githubAgentAuthDir() {
1782
1914
  const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
1783
1915
  if (override) return override;
1784
- return (0, import_node_path12.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
1916
+ return (0, import_node_path13.join)((0, import_node_os4.homedir)(), ".sideboard-git-auth");
1785
1917
  }
1786
1918
  function githubCredentialStorePath() {
1787
- return (0, import_node_path12.join)(githubAgentAuthDir(), "git-credentials");
1919
+ return (0, import_node_path13.join)(githubAgentAuthDir(), "git-credentials");
1788
1920
  }
1789
1921
  function githubGhConfigDir() {
1790
- return (0, import_node_path12.join)(githubAgentAuthDir(), "gh");
1922
+ return (0, import_node_path13.join)(githubAgentAuthDir(), "gh");
1791
1923
  }
1792
1924
  function writePrivateFile2(file, body) {
1793
- (0, import_node_fs11.mkdirSync)((0, import_node_path12.dirname)(file), { recursive: true, mode: 448 });
1925
+ (0, import_node_fs12.mkdirSync)((0, import_node_path13.dirname)(file), { recursive: true, mode: 448 });
1794
1926
  try {
1795
- (0, import_node_fs11.chmodSync)((0, import_node_path12.dirname)(file), 448);
1927
+ (0, import_node_fs12.chmodSync)((0, import_node_path13.dirname)(file), 448);
1796
1928
  } catch {
1797
1929
  }
1798
- (0, import_node_fs11.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
1930
+ (0, import_node_fs12.writeFileSync)(file, body, { encoding: "utf8", mode: 384 });
1799
1931
  try {
1800
- (0, import_node_fs11.chmodSync)(file, 384);
1932
+ (0, import_node_fs12.chmodSync)(file, 384);
1801
1933
  } catch {
1802
1934
  }
1803
1935
  }
@@ -1822,19 +1954,19 @@ function materializeGithubAgentAuth(token, user) {
1822
1954
  const trimmed = token.trim();
1823
1955
  if (!trimmed) return;
1824
1956
  const root = githubAgentAuthDir();
1825
- (0, import_node_fs11.mkdirSync)(root, { recursive: true, mode: 448 });
1957
+ (0, import_node_fs12.mkdirSync)(root, { recursive: true, mode: 448 });
1826
1958
  try {
1827
- (0, import_node_fs11.chmodSync)(root, 448);
1959
+ (0, import_node_fs12.chmodSync)(root, 448);
1828
1960
  } catch {
1829
1961
  }
1830
1962
  writePrivateFile2(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
1831
1963
  const ghDir = githubGhConfigDir();
1832
- (0, import_node_fs11.mkdirSync)(ghDir, { recursive: true, mode: 448 });
1833
- writePrivateFile2((0, import_node_path12.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
1834
- writePrivateFile2((0, import_node_path12.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
1964
+ (0, import_node_fs12.mkdirSync)(ghDir, { recursive: true, mode: 448 });
1965
+ writePrivateFile2((0, import_node_path13.join)(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
1966
+ writePrivateFile2((0, import_node_path13.join)(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
1835
1967
  }
1836
1968
  function githubAgentAuthReady() {
1837
- return (0, import_node_fs11.existsSync)(githubCredentialStorePath()) && (0, import_node_fs11.existsSync)((0, import_node_path12.join)(githubGhConfigDir(), "hosts.yml"));
1969
+ return (0, import_node_fs12.existsSync)(githubCredentialStorePath()) && (0, import_node_fs12.existsSync)((0, import_node_path13.join)(githubGhConfigDir(), "hosts.yml"));
1838
1970
  }
1839
1971
  function githubCredentialHelperGitConfig() {
1840
1972
  const file = githubCredentialStorePath();
@@ -1849,13 +1981,13 @@ function githubGhConfigEnv() {
1849
1981
  GH_PROMPT_DISABLED: "1"
1850
1982
  };
1851
1983
  }
1852
- var import_node_fs11, import_node_os4, import_node_path12;
1984
+ var import_node_fs12, import_node_os4, import_node_path13;
1853
1985
  var init_github_agent_auth = __esm({
1854
1986
  "src/git/github-agent-auth.ts"() {
1855
1987
  "use strict";
1856
- import_node_fs11 = require("fs");
1988
+ import_node_fs12 = require("fs");
1857
1989
  import_node_os4 = require("os");
1858
- import_node_path12 = require("path");
1990
+ import_node_path13 = require("path");
1859
1991
  }
1860
1992
  });
1861
1993
 
@@ -1864,11 +1996,11 @@ function isIndexLockError(text7) {
1864
1996
  return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text7);
1865
1997
  }
1866
1998
  function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
1867
- const lockPath = (0, import_node_path13.join)(gitDir, "index.lock");
1999
+ const lockPath = (0, import_node_path14.join)(gitDir, "index.lock");
1868
2000
  try {
1869
- if (!(0, import_node_fs12.existsSync)(lockPath)) return null;
1870
- if (now - (0, import_node_fs12.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
1871
- (0, import_node_fs12.unlinkSync)(lockPath);
2001
+ if (!(0, import_node_fs13.existsSync)(lockPath)) return null;
2002
+ if (now - (0, import_node_fs13.statSync)(lockPath).mtimeMs < maxAgeMs) return null;
2003
+ (0, import_node_fs13.unlinkSync)(lockPath);
1872
2004
  return lockPath;
1873
2005
  } catch {
1874
2006
  return null;
@@ -1883,12 +2015,12 @@ function clearStaleIndexLocks(gitDirs, maxAgeMs = STALE_INDEX_LOCK_MS) {
1883
2015
  }
1884
2016
  return removed;
1885
2017
  }
1886
- var import_node_fs12, import_node_path13, STALE_INDEX_LOCK_MS;
2018
+ var import_node_fs13, import_node_path14, STALE_INDEX_LOCK_MS;
1887
2019
  var init_stale_lock = __esm({
1888
2020
  "src/git/stale-lock.ts"() {
1889
2021
  "use strict";
1890
- import_node_fs12 = require("fs");
1891
- import_node_path13 = require("path");
2022
+ import_node_fs13 = require("fs");
2023
+ import_node_path14 = require("path");
1892
2024
  STALE_INDEX_LOCK_MS = 2e4;
1893
2025
  }
1894
2026
  });
@@ -2998,11 +3130,11 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
2998
3130
  if (gitDir.exitCode !== 0) return;
2999
3131
  const dir = gitDir.stdout.trim();
3000
3132
  if (!dir) return;
3001
- const excludePath = (0, import_node_path14.join)(dir, "info", "exclude");
3002
- (0, import_node_fs13.mkdirSync)((0, import_node_path14.dirname)(excludePath), { recursive: true });
3133
+ const excludePath = (0, import_node_path15.join)(dir, "info", "exclude");
3134
+ (0, import_node_fs14.mkdirSync)((0, import_node_path15.dirname)(excludePath), { recursive: true });
3003
3135
  let body = "";
3004
3136
  try {
3005
- body = (0, import_node_fs13.readFileSync)(excludePath, "utf8");
3137
+ body = (0, import_node_fs14.readFileSync)(excludePath, "utf8");
3006
3138
  } catch {
3007
3139
  body = "";
3008
3140
  }
@@ -3018,7 +3150,7 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
3018
3150
  ` : body;
3019
3151
  const header = body.includes(EXCLUDE_COMMENT) ? "" : `${EXCLUDE_COMMENT}
3020
3152
  `;
3021
- (0, import_node_fs13.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
3153
+ (0, import_node_fs14.writeFileSync)(excludePath, `${prefix}${header}${missing.join("\n")}
3022
3154
  `, "utf8");
3023
3155
  }
3024
3156
  const listed = await git(["ls-files", "-z", "--", ".sideboard"], worktreePath, {
@@ -3033,12 +3165,12 @@ async function ensureWorktreeSideboardIgnored(worktreePath) {
3033
3165
  timeoutMs: 8e3
3034
3166
  });
3035
3167
  }
3036
- var import_node_fs13, import_node_path14, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
3168
+ var import_node_fs14, import_node_path15, WORKTREE_SIDEBOARD_EXCLUDE, WORKTREE_CONTEXT_EXCLUDE, EXCLUDE_COMMENT;
3037
3169
  var init_worktree_exclude = __esm({
3038
3170
  "src/git/worktree-exclude.ts"() {
3039
3171
  "use strict";
3040
- import_node_fs13 = require("fs");
3041
- import_node_path14 = require("path");
3172
+ import_node_fs14 = require("fs");
3173
+ import_node_path15 = require("path");
3042
3174
  init_run();
3043
3175
  WORKTREE_SIDEBOARD_EXCLUDE = ".sideboard/";
3044
3176
  WORKTREE_CONTEXT_EXCLUDE = ".context/";
@@ -3189,7 +3321,7 @@ var init_account_profile = __esm({
3189
3321
 
3190
3322
  // src/store/secret-vault.ts
3191
3323
  function secretVaultPath() {
3192
- return (0, import_node_path15.join)(appDataDir(), "secrets.json");
3324
+ return (0, import_node_path16.join)(appDataDir(), "secrets.json");
3193
3325
  }
3194
3326
  function loadSecretVault() {
3195
3327
  const parsed = readSecureJson(secretVaultPath());
@@ -3248,11 +3380,11 @@ function normalizeVault(raw) {
3248
3380
  }
3249
3381
  return out;
3250
3382
  }
3251
- var import_node_path15;
3383
+ var import_node_path16;
3252
3384
  var init_secret_vault = __esm({
3253
3385
  "src/store/secret-vault.ts"() {
3254
3386
  "use strict";
3255
- import_node_path15 = require("path");
3387
+ import_node_path16 = require("path");
3256
3388
  init_paths();
3257
3389
  init_secure_file();
3258
3390
  }
@@ -3433,10 +3565,10 @@ function toPublicAppSettings(settings) {
3433
3565
  };
3434
3566
  }
3435
3567
  function appSettingsPath() {
3436
- return (0, import_node_path16.join)(appDataDir(), "settings.json");
3568
+ return (0, import_node_path17.join)(appDataDir(), "settings.json");
3437
3569
  }
3438
3570
  function claudeUserSettingsPath() {
3439
- return (0, import_node_path16.join)((0, import_node_os5.homedir)(), ".claude", "settings.json");
3571
+ return (0, import_node_path17.join)((0, import_node_os5.homedir)(), ".claude", "settings.json");
3440
3572
  }
3441
3573
  function normalizeClaude(raw) {
3442
3574
  if (!raw || typeof raw !== "object") return {};
@@ -3444,7 +3576,7 @@ function normalizeClaude(raw) {
3444
3576
  const out = {};
3445
3577
  if (typeof source.executablePath === "string") {
3446
3578
  const path = source.executablePath.trim();
3447
- if (path && (0, import_node_path16.isAbsolute)(path)) out.executablePath = path;
3579
+ if (path && (0, import_node_path17.isAbsolute)(path)) out.executablePath = path;
3448
3580
  }
3449
3581
  if (typeof source.chromeEnabled === "boolean") {
3450
3582
  out.chromeEnabled = source.chromeEnabled;
@@ -3457,13 +3589,13 @@ function normalizeCliExecutable(raw) {
3457
3589
  const out = {};
3458
3590
  if (typeof source.executablePath === "string") {
3459
3591
  const path = source.executablePath.trim();
3460
- if (path && (0, import_node_path16.isAbsolute)(path)) out.executablePath = path;
3592
+ if (path && (0, import_node_path17.isAbsolute)(path)) out.executablePath = path;
3461
3593
  }
3462
3594
  return out;
3463
3595
  }
3464
3596
  function absoluteExecutablePath(value) {
3465
3597
  const path = value.trim();
3466
- if (!(0, import_node_path16.isAbsolute)(path)) {
3598
+ if (!(0, import_node_path17.isAbsolute)(path)) {
3467
3599
  throw new Error("Executable path must be absolute. Leave it empty to use the system CLI.");
3468
3600
  }
3469
3601
  return path;
@@ -3474,7 +3606,7 @@ function normalizeBrightsy(raw) {
3474
3606
  const out = {};
3475
3607
  if (typeof source.executablePath === "string") {
3476
3608
  const path = source.executablePath.trim();
3477
- if (path && (0, import_node_path16.isAbsolute)(path)) out.executablePath = path;
3609
+ if (path && (0, import_node_path17.isAbsolute)(path)) out.executablePath = path;
3478
3610
  }
3479
3611
  if (typeof source.cloudConnectEnabled === "boolean") {
3480
3612
  out.cloudConnectEnabled = source.cloudConnectEnabled;
@@ -3818,10 +3950,10 @@ function normalizeSettings(raw) {
3818
3950
  }
3819
3951
  function readSettingsFile() {
3820
3952
  const path = appSettingsPath();
3821
- if (!(0, import_node_fs14.existsSync)(path)) return { ...EMPTY_SETTINGS };
3953
+ if (!(0, import_node_fs15.existsSync)(path)) return { ...EMPTY_SETTINGS };
3822
3954
  try {
3823
3955
  chmodOwnerOnly(path);
3824
- const parsed = JSON.parse((0, import_node_fs14.readFileSync)(path, "utf8"));
3956
+ const parsed = JSON.parse((0, import_node_fs15.readFileSync)(path, "utf8"));
3825
3957
  return normalizeSettings(parsed);
3826
3958
  } catch {
3827
3959
  return { ...EMPTY_SETTINGS };
@@ -4744,14 +4876,14 @@ function childEnvWithAppSettings(extra) {
4744
4876
  function harnessEnvKey(harness) {
4745
4877
  return HARNESS_ENV_KEYS[harness];
4746
4878
  }
4747
- var import_node_crypto3, import_node_fs14, import_node_os5, import_node_path16, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
4879
+ var import_node_crypto3, import_node_fs15, import_node_os5, import_node_path17, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, FOLLOW_UP_BEHAVIORS, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, CONFIRM_ACCOUNT, CONFIRM_PROJECT, DEFAULT_CLI_BIN;
4748
4880
  var init_app_settings = __esm({
4749
4881
  "src/store/app-settings.ts"() {
4750
4882
  "use strict";
4751
4883
  import_node_crypto3 = require("crypto");
4752
- import_node_fs14 = require("fs");
4884
+ import_node_fs15 = require("fs");
4753
4885
  import_node_os5 = require("os");
4754
- import_node_path16 = require("path");
4886
+ import_node_path17 = require("path");
4755
4887
  init_orchestrator_capable();
4756
4888
  init_thinking_effort();
4757
4889
  init_nested_electron_env();
@@ -4917,7 +5049,7 @@ async function warmGithubAgentAuth(opts) {
4917
5049
  }
4918
5050
  function normalizeWritableRoot(raw) {
4919
5051
  const trimmed = raw.trim().replace(/\/+$/, "");
4920
- return trimmed && (0, import_node_path17.isAbsolute)(trimmed) ? trimmed : null;
5052
+ return trimmed && (0, import_node_path18.isAbsolute)(trimmed) ? trimmed : null;
4921
5053
  }
4922
5054
  async function resolveCodexGitWritableRoots(cwd) {
4923
5055
  const roots = /* @__PURE__ */ new Set();
@@ -4995,11 +5127,11 @@ function formatGitAuthModeDirective(mode) {
4995
5127
  ].join("\n");
4996
5128
  }
4997
5129
  }
4998
- var import_node_path17, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
5130
+ var import_node_path18, HTTPS_REWRITE, TOKEN_TTL_MS, tokenMemo, GITHUB_CHILD_TOKEN_KEYS;
4999
5131
  var init_git_auth_mode = __esm({
5000
5132
  "src/git/git-auth-mode.ts"() {
5001
5133
  "use strict";
5002
- import_node_path17 = require("path");
5134
+ import_node_path18 = require("path");
5003
5135
  init_app_settings();
5004
5136
  init_github_agent_auth();
5005
5137
  init_run();
@@ -5823,7 +5955,7 @@ async function resolveRepoRoot(cwd) {
5823
5955
  }
5824
5956
  function canonicalizeRepoPath(path) {
5825
5957
  try {
5826
- return (0, import_node_fs15.realpathSync)(path);
5958
+ return (0, import_node_fs16.realpathSync)(path);
5827
5959
  } catch {
5828
5960
  return path.replace(/\/+$/, "");
5829
5961
  }
@@ -6667,8 +6799,8 @@ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
6667
6799
  }
6668
6800
  async function createThreadWorktree(opts) {
6669
6801
  let branchName = `thread/${opts.slug}`;
6670
- const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
6671
- if ((0, import_node_fs15.existsSync)(worktreePath)) {
6802
+ const worktreePath = (0, import_node_path19.join)(worktreesRoot(opts.repoPath), opts.slug);
6803
+ if ((0, import_node_fs16.existsSync)(worktreePath)) {
6672
6804
  throw new Error(`Worktree already exists at ${worktreePath}`);
6673
6805
  }
6674
6806
  await ensureGhPreferOrigin(opts.repoPath);
@@ -6709,8 +6841,8 @@ ${add.stdout}`;
6709
6841
  async function createExistingBranchWorktree(opts) {
6710
6842
  const branchName = opts.branchName.trim();
6711
6843
  if (!branchName) throw new Error("branch name required");
6712
- const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
6713
- if ((0, import_node_fs15.existsSync)(worktreePath)) {
6844
+ const worktreePath = (0, import_node_path19.join)(worktreesRoot(opts.repoPath), opts.slug);
6845
+ if ((0, import_node_fs16.existsSync)(worktreePath)) {
6714
6846
  throw new Error(`Worktree already exists at ${worktreePath}`);
6715
6847
  }
6716
6848
  await ensureGhPreferOrigin(opts.repoPath);
@@ -6991,11 +7123,11 @@ async function createOrUpdatePr(worktreePath, opts) {
6991
7123
  const headRef = ghHeadRef(slug, opts.head);
6992
7124
  const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
6993
7125
  const bodyText = clampGithubPrBody(opts.body ?? opts.title);
6994
- const bodyFile = (0, import_node_path18.join)(
7126
+ const bodyFile = (0, import_node_path19.join)(
6995
7127
  (0, import_node_os6.tmpdir)(),
6996
7128
  `sideboard-pr-body-${process.pid}-${(0, import_node_crypto4.randomBytes)(6).toString("hex")}.md`
6997
7129
  );
6998
- (0, import_node_fs15.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
7130
+ (0, import_node_fs16.writeFileSync)(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
6999
7131
  `, "utf8");
7000
7132
  const bodyArgs = ["--body-file", bodyFile];
7001
7133
  try {
@@ -7009,7 +7141,7 @@ async function createOrUpdatePr(worktreePath, opts) {
7009
7141
  });
7010
7142
  } finally {
7011
7143
  try {
7012
- (0, import_node_fs15.unlinkSync)(bodyFile);
7144
+ (0, import_node_fs16.unlinkSync)(bodyFile);
7013
7145
  } catch {
7014
7146
  }
7015
7147
  }
@@ -7091,10 +7223,10 @@ function sameRepoPath(a, b) {
7091
7223
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
7092
7224
  }
7093
7225
  function listLocalThreadBranchSlugs(repoPath) {
7094
- const refsDir = (0, import_node_path18.join)(repoPath, ".git", "refs", "heads", "thread");
7095
- if (!(0, import_node_fs15.existsSync)(refsDir)) return [];
7226
+ const refsDir = (0, import_node_path19.join)(repoPath, ".git", "refs", "heads", "thread");
7227
+ if (!(0, import_node_fs16.existsSync)(refsDir)) return [];
7096
7228
  try {
7097
- return (0, import_node_fs15.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
7229
+ return (0, import_node_fs16.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
7098
7230
  } catch {
7099
7231
  return [];
7100
7232
  }
@@ -7102,8 +7234,8 @@ function listLocalThreadBranchSlugs(repoPath) {
7102
7234
  function collectTakenTeamSlugs(repoPath) {
7103
7235
  const taken = /* @__PURE__ */ new Set();
7104
7236
  const root = worktreesRoot(repoPath);
7105
- if ((0, import_node_fs15.existsSync)(root)) {
7106
- for (const entry of (0, import_node_fs15.readdirSync)(root, { withFileTypes: true })) {
7237
+ if ((0, import_node_fs16.existsSync)(root)) {
7238
+ for (const entry of (0, import_node_fs16.readdirSync)(root, { withFileTypes: true })) {
7107
7239
  if (entry.isDirectory() && entry.name !== ".DS_Store") {
7108
7240
  for (const slug of takenSlugsFromThread({ worktreePath: entry.name })) {
7109
7241
  taken.add(slug);
@@ -7128,20 +7260,20 @@ function allocateTeamSlug(repoPath) {
7128
7260
  const taken = collectTakenTeamSlugs(repoPath);
7129
7261
  for (let attempt = 0; attempt < 32; attempt++) {
7130
7262
  const team = allocateTeamName(taken);
7131
- const path = (0, import_node_path18.join)(worktreesRoot(repoPath), team.slug);
7132
- if (!(0, import_node_fs15.existsSync)(path)) return team;
7263
+ const path = (0, import_node_path19.join)(worktreesRoot(repoPath), team.slug);
7264
+ if (!(0, import_node_fs16.existsSync)(path)) return team;
7133
7265
  taken.add(team.slug);
7134
7266
  }
7135
7267
  throw new Error("No available soccer team worktree directories left");
7136
7268
  }
7137
- var import_node_crypto4, import_node_fs15, import_node_os6, import_node_path18, PR_DETAILS_JSON_FIELDS;
7269
+ var import_node_crypto4, import_node_fs16, import_node_os6, import_node_path19, PR_DETAILS_JSON_FIELDS;
7138
7270
  var init_worktree = __esm({
7139
7271
  "src/git/worktree.ts"() {
7140
7272
  "use strict";
7141
7273
  import_node_crypto4 = require("crypto");
7142
- import_node_fs15 = require("fs");
7274
+ import_node_fs16 = require("fs");
7143
7275
  import_node_os6 = require("os");
7144
- import_node_path18 = require("path");
7276
+ import_node_path19 = require("path");
7145
7277
  init_paths();
7146
7278
  init_thread_store();
7147
7279
  init_teams();
@@ -7213,7 +7345,7 @@ var init_cloud_connect_constants = __esm({
7213
7345
 
7214
7346
  // src/composer/stage-files.ts
7215
7347
  function fileExtension(filePath) {
7216
- const base = (0, import_node_path19.basename)(filePath).toLowerCase();
7348
+ const base = (0, import_node_path20.basename)(filePath).toLowerCase();
7217
7349
  return base.includes(".") ? base.split(".").pop() || "" : "";
7218
7350
  }
7219
7351
  function isImageFilePath(filePath) {
@@ -7223,22 +7355,22 @@ function imageMimeType(filePath) {
7223
7355
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
7224
7356
  }
7225
7357
  function ensureAttachmentsDir(worktreePath) {
7226
- const dir = (0, import_node_path19.join)(worktreePath, ATTACHMENTS_DIR);
7227
- (0, import_node_fs16.mkdirSync)(dir, { recursive: true });
7228
- const gi = (0, import_node_path19.join)(dir, ".gitignore");
7229
- if (!(0, import_node_fs16.existsSync)(gi)) {
7230
- (0, import_node_fs16.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
7358
+ const dir = (0, import_node_path20.join)(worktreePath, ATTACHMENTS_DIR);
7359
+ (0, import_node_fs17.mkdirSync)(dir, { recursive: true });
7360
+ const gi = (0, import_node_path20.join)(dir, ".gitignore");
7361
+ if (!(0, import_node_fs17.existsSync)(gi)) {
7362
+ (0, import_node_fs17.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
7231
7363
  }
7232
7364
  return dir;
7233
7365
  }
7234
7366
  function uniqueAttachmentName(dir, originalName) {
7235
7367
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
7236
- if (!(0, import_node_fs16.existsSync)((0, import_node_path19.join)(dir, safe))) return safe;
7237
- const ext = (0, import_node_path19.extname)(safe);
7368
+ if (!(0, import_node_fs17.existsSync)((0, import_node_path20.join)(dir, safe))) return safe;
7369
+ const ext = (0, import_node_path20.extname)(safe);
7238
7370
  const stem = ext ? safe.slice(0, -ext.length) : safe;
7239
7371
  for (let i = 1; i < 1e4; i++) {
7240
7372
  const candidate = `${stem}-${i}${ext}`;
7241
- if (!(0, import_node_fs16.existsSync)((0, import_node_path19.join)(dir, candidate))) return candidate;
7373
+ if (!(0, import_node_fs17.existsSync)((0, import_node_path20.join)(dir, candidate))) return candidate;
7242
7374
  }
7243
7375
  return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
7244
7376
  }
@@ -7294,15 +7426,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
7294
7426
  const dir = ensureAttachmentsDir(worktreePath);
7295
7427
  const out = [];
7296
7428
  for (const abs of absolutePaths) {
7297
- const originalName = (0, import_node_path19.basename)(abs);
7429
+ const originalName = (0, import_node_path20.basename)(abs);
7298
7430
  try {
7299
- const st = (0, import_node_fs16.statSync)(abs);
7431
+ const st = (0, import_node_fs17.statSync)(abs);
7300
7432
  if (!st.isFile()) continue;
7301
7433
  const name = uniqueAttachmentName(dir, originalName);
7302
- const destAbs = (0, import_node_path19.join)(dir, name);
7303
- (0, import_node_fs16.copyFileSync)(abs, destAbs);
7434
+ const destAbs = (0, import_node_path20.join)(dir, name);
7435
+ (0, import_node_fs17.copyFileSync)(abs, destAbs);
7304
7436
  const rel = `${ATTACHMENTS_DIR}/${name}`;
7305
- const buf = (0, import_node_fs16.readFileSync)(destAbs);
7437
+ const buf = (0, import_node_fs17.readFileSync)(destAbs);
7306
7438
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
7307
7439
  } catch (err) {
7308
7440
  out.push({
@@ -7324,8 +7456,8 @@ function stageBuffersAsAttachments(worktreePath, buffers2) {
7324
7456
  try {
7325
7457
  const buf = Buffer.from(item.dataBase64, "base64");
7326
7458
  const name = uniqueAttachmentName(dir, originalName);
7327
- const destAbs = (0, import_node_path19.join)(dir, name);
7328
- (0, import_node_fs16.writeFileSync)(destAbs, buf);
7459
+ const destAbs = (0, import_node_path20.join)(dir, name);
7460
+ (0, import_node_fs17.writeFileSync)(destAbs, buf);
7329
7461
  const rel = `${ATTACHMENTS_DIR}/${name}`;
7330
7462
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
7331
7463
  } catch (err) {
@@ -7386,18 +7518,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
7386
7518
  if (!rel || rel.includes("..") || rel.startsWith("/")) {
7387
7519
  out.push({
7388
7520
  id: (0, import_node_crypto5.randomUUID)(),
7389
- name: (0, import_node_path19.basename)(rel) || "file",
7521
+ name: (0, import_node_path20.basename)(rel) || "file",
7390
7522
  kind: "file",
7391
7523
  content: `(invalid path: ${rel})`
7392
7524
  });
7393
7525
  continue;
7394
7526
  }
7395
- const name = (0, import_node_path19.basename)(rel);
7527
+ const name = (0, import_node_path20.basename)(rel);
7396
7528
  try {
7397
- const abs = (0, import_node_path19.join)(worktreePath, rel);
7398
- const st = (0, import_node_fs16.statSync)(abs);
7529
+ const abs = (0, import_node_path20.join)(worktreePath, rel);
7530
+ const st = (0, import_node_fs17.statSync)(abs);
7399
7531
  if (!st.isFile()) continue;
7400
- const buf = (0, import_node_fs16.readFileSync)(abs);
7532
+ const buf = (0, import_node_fs17.readFileSync)(abs);
7401
7533
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
7402
7534
  } catch (err) {
7403
7535
  out.push({
@@ -7410,12 +7542,12 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
7410
7542
  }
7411
7543
  return out;
7412
7544
  }
7413
- var import_node_fs16, import_node_path19, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
7545
+ var import_node_fs17, import_node_path20, import_node_crypto5, IMAGE_EXTENSIONS, IMAGE_MIME_BY_EXT, MAX_INLINE_BYTES, MAX_PREVIEW_BYTES, IMAGE_HINT_RE, PLACEHOLDER_CONTENT_RE;
7414
7546
  var init_stage_files = __esm({
7415
7547
  "src/composer/stage-files.ts"() {
7416
7548
  "use strict";
7417
- import_node_fs16 = require("fs");
7418
- import_node_path19 = require("path");
7549
+ import_node_fs17 = require("fs");
7550
+ import_node_path20 = require("path");
7419
7551
  import_node_crypto5 = require("crypto");
7420
7552
  init_workspace_scratch();
7421
7553
  IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
@@ -7455,38 +7587,38 @@ __export(workspaces_exports, {
7455
7587
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
7456
7588
  });
7457
7589
  function workspacesFile() {
7458
- return (0, import_node_path20.join)(appDataDir(), "workspaces.json");
7590
+ return (0, import_node_path21.join)(appDataDir(), "workspaces.json");
7459
7591
  }
7460
7592
  function removedWorkspacesFile() {
7461
- return (0, import_node_path20.join)(appDataDir(), "removed-workspaces.json");
7593
+ return (0, import_node_path21.join)(appDataDir(), "removed-workspaces.json");
7462
7594
  }
7463
7595
  function readAll() {
7464
7596
  const path = workspacesFile();
7465
- if (!(0, import_node_fs17.existsSync)(path)) return [];
7597
+ if (!(0, import_node_fs18.existsSync)(path)) return [];
7466
7598
  try {
7467
- const raw = JSON.parse((0, import_node_fs17.readFileSync)(path, "utf8"));
7599
+ const raw = JSON.parse((0, import_node_fs18.readFileSync)(path, "utf8"));
7468
7600
  return Array.isArray(raw) ? raw : [];
7469
7601
  } catch {
7470
7602
  return [];
7471
7603
  }
7472
7604
  }
7473
7605
  function writeAll(list) {
7474
- (0, import_node_fs17.mkdirSync)(appDataDir(), { recursive: true });
7475
- (0, import_node_fs17.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
7606
+ (0, import_node_fs18.mkdirSync)(appDataDir(), { recursive: true });
7607
+ (0, import_node_fs18.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
7476
7608
  }
7477
7609
  function readRemoved() {
7478
7610
  const path = removedWorkspacesFile();
7479
- if (!(0, import_node_fs17.existsSync)(path)) return /* @__PURE__ */ new Set();
7611
+ if (!(0, import_node_fs18.existsSync)(path)) return /* @__PURE__ */ new Set();
7480
7612
  try {
7481
- const raw = JSON.parse((0, import_node_fs17.readFileSync)(path, "utf8"));
7613
+ const raw = JSON.parse((0, import_node_fs18.readFileSync)(path, "utf8"));
7482
7614
  return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
7483
7615
  } catch {
7484
7616
  return /* @__PURE__ */ new Set();
7485
7617
  }
7486
7618
  }
7487
7619
  function writeRemoved(paths) {
7488
- (0, import_node_fs17.mkdirSync)(appDataDir(), { recursive: true });
7489
- (0, import_node_fs17.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
7620
+ (0, import_node_fs18.mkdirSync)(appDataDir(), { recursive: true });
7621
+ (0, import_node_fs18.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
7490
7622
  }
7491
7623
  function rememberRemoved(repoPath) {
7492
7624
  const next = readRemoved();
@@ -7509,7 +7641,7 @@ function listWorkspaces() {
7509
7641
  async function addWorkspace(repoPath) {
7510
7642
  const root = await resolveRepoRoot(repoPath);
7511
7643
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
7512
- if (!(0, import_node_fs17.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
7644
+ if (!(0, import_node_fs18.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
7513
7645
  forgetRemoved(root);
7514
7646
  await ensureGhPreferOrigin(root);
7515
7647
  const current = readAll();
@@ -7517,7 +7649,7 @@ async function addWorkspace(repoPath) {
7517
7649
  if (existing) return existing;
7518
7650
  const next = {
7519
7651
  path: root,
7520
- name: (0, import_node_path20.basename)(root),
7652
+ name: (0, import_node_path21.basename)(root),
7521
7653
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
7522
7654
  };
7523
7655
  writeAll([...current, next]);
@@ -7539,10 +7671,10 @@ function syncWorkspacesFromThreads(repoPaths) {
7539
7671
  if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
7540
7672
  continue;
7541
7673
  }
7542
- if (!(0, import_node_fs17.existsSync)(path)) continue;
7674
+ if (!(0, import_node_fs18.existsSync)(path)) continue;
7543
7675
  const ws = {
7544
7676
  path,
7545
- name: (0, import_node_path20.basename)(path),
7677
+ name: (0, import_node_path21.basename)(path),
7546
7678
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
7547
7679
  };
7548
7680
  byPath.set(path, ws);
@@ -7552,12 +7684,12 @@ function syncWorkspacesFromThreads(repoPaths) {
7552
7684
  if (dirty) writeAll(next);
7553
7685
  return next.sort((a, b) => a.name.localeCompare(b.name));
7554
7686
  }
7555
- var import_node_fs17, import_node_path20;
7687
+ var import_node_fs18, import_node_path21;
7556
7688
  var init_workspaces2 = __esm({
7557
7689
  "src/store/workspaces.ts"() {
7558
7690
  "use strict";
7559
- import_node_fs17 = require("fs");
7560
- import_node_path20 = require("path");
7691
+ import_node_fs18 = require("fs");
7692
+ import_node_path21 = require("path");
7561
7693
  init_paths();
7562
7694
  init_global_workspace();
7563
7695
  init_worktree();
@@ -7668,7 +7800,7 @@ function coordinatorTurnReminder(opts) {
7668
7800
  function ensureGlobalCoordinatorCwd(opts) {
7669
7801
  const dir = globalAgentCwd();
7670
7802
  try {
7671
- (0, import_node_fs18.mkdirSync)(dir, { recursive: true });
7803
+ (0, import_node_fs19.mkdirSync)(dir, { recursive: true });
7672
7804
  } catch {
7673
7805
  return dir;
7674
7806
  }
@@ -7676,7 +7808,7 @@ function ensureGlobalCoordinatorCwd(opts) {
7676
7808
  let orchId = opts?.orchestratorThreadId?.trim() || "";
7677
7809
  if (!orchId) {
7678
7810
  try {
7679
- const existing = (0, import_node_fs18.readFileSync)((0, import_node_path21.join)(dir, "AGENTS.md"), "utf8");
7811
+ const existing = (0, import_node_fs19.readFileSync)((0, import_node_path22.join)(dir, "AGENTS.md"), "utf8");
7680
7812
  const m = existing.match(
7681
7813
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
7682
7814
  );
@@ -7711,8 +7843,8 @@ function ensureGlobalCoordinatorCwd(opts) {
7711
7843
  "",
7712
7844
  "When creating threads, pass `repoPath` from `list_workspaces` (or the path you just registered).",
7713
7845
  orchId ? `Pass parentThreadId="${orchId}" (or omit it). Never invent another parentThreadId.` : "Pass `parentThreadId` for children (this chat's id from the turn reminder).",
7714
- "Omit `agent` / `model` on `create_thread` unless you have a reason to override Account defaults.",
7715
- "Never pass `agent=codex` when you yourself are Codex \u2014 nested Codex deadlocks on shared ~/.codex locks. Omit agent (Account default) or use cursor/claude.",
7846
+ "Omit `agent` / `model` on `create_thread`. Sideboard applies Settings \u2192 Default agent, model & effort. Do not pass your own agent or `agent=cursor` \u2014 those are ignored.",
7847
+ "Never pass `agent=codex` when you yourself are Codex \u2014 nested Codex can deadlock on shared ~/.codex locks. Omit agent; Sideboard applies Account defaults, and switches that nested-Codex case to Cursor only when a CURSOR_API_KEY is configured.",
7716
7848
  "Typical flow (Home board): list_board \u2192 create_thread (sourceType=ticket|pr|branch) \u2192 send_to_thread \u2192 wait_for_turn (loop while stillRunning) \u2192 ask_git create-draft \u2192 wait_for_turn. Merge only if the user explicitly asked (`ask_git` merge).",
7717
7849
  "Typical flow (branch / explicit source): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn (loop while stillRunning) \u2192 ask_git create-draft.",
7718
7850
  "Typical flow (find work): list_workspaces \u2192 pick repo(s) matching account / project context \u2192 Sideboard list_issues / linear_* (tickets) or list_prs(queue=review) (reviews) \u2192 show the options. Never wait on Claude Linear MCP. Only create_thread + send_to_thread when they asked to start (e.g. \u201Cfind me work and start it\u201D) \u2014 then wait_for_turn (loop while stillRunning) \u2192 ask_git create-draft.",
@@ -7721,9 +7853,9 @@ function ensureGlobalCoordinatorCwd(opts) {
7721
7853
  "Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). If the user gave a goal (Greptile 5/5, CI green), pass that goal through so they watch-fix-push until it lands \u2014 do not start that loop on a plain push, and do not tell the human to poll. Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
7722
7854
  ].join("\n");
7723
7855
  try {
7724
- (0, import_node_fs18.writeFileSync)((0, import_node_path21.join)(dir, "CLAUDE.md"), `${body}
7856
+ (0, import_node_fs19.writeFileSync)((0, import_node_path22.join)(dir, "CLAUDE.md"), `${body}
7725
7857
  `, "utf8");
7726
- (0, import_node_fs18.writeFileSync)((0, import_node_path21.join)(dir, "AGENTS.md"), `${body}
7858
+ (0, import_node_fs19.writeFileSync)((0, import_node_path22.join)(dir, "AGENTS.md"), `${body}
7727
7859
  `, "utf8");
7728
7860
  } catch {
7729
7861
  }
@@ -7755,12 +7887,12 @@ function coordinatorSystemPrompt(opts) {
7755
7887
  formatWorkspaceInventory(opts.workspaces)
7756
7888
  ].join("\n");
7757
7889
  }
7758
- var import_node_fs18, import_node_path21, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
7890
+ var import_node_fs19, import_node_path22, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
7759
7891
  var init_coordinator_prompt = __esm({
7760
7892
  "src/orchestrator/coordinator-prompt.ts"() {
7761
7893
  "use strict";
7762
- import_node_fs18 = require("fs");
7763
- import_node_path21 = require("path");
7894
+ import_node_fs19 = require("fs");
7895
+ import_node_path22 = require("path");
7764
7896
  init_worktree();
7765
7897
  init_app_settings();
7766
7898
  init_paths();
@@ -7789,7 +7921,7 @@ var init_coordinator_prompt = __esm({
7789
7921
  "Workspaces:",
7790
7922
  "- add_workspace / remove_workspace \u2014 register or unregister a git repo",
7791
7923
  "Worktree threads (chats):",
7792
- "- create_thread \u2014 create a worktree + chat from branch | pr | ticket (appears on Home). Do not create a second worktree for a ticket, PR, or named branch that already has one \u2014 that call returns the live thread (alreadyStarted=true). Creating from the default branch still opens a new isolated worktree. Pass repoPath + parentThreadId; omit agent and model to use Sideboard Account defaults (Settings \u2192 Default agent, model & effort). If the repo has a setup script, Sideboard runs it in the background (does not block send_to_thread). If you are Codex, do not set agent=codex (nested Codex deadlocks)",
7924
+ "- create_thread \u2014 create a worktree + chat from branch | pr | ticket (appears on Home). Do not create a second worktree for a ticket, PR, or named branch that already has one \u2014 that call returns the live thread (alreadyStarted=true). Creating from the default branch still opens a new isolated worktree. Pass repoPath + parentThreadId; omit agent and model so Sideboard applies Settings \u2192 Default agent, model & effort (never pass your own agent or agent=cursor). If the repo has a setup script, Sideboard runs it in the background (does not block send_to_thread). Nested Codex (you are Codex and the child would be Codex) can deadlock on ~/.codex locks \u2014 omit agent; Sideboard switches the child to Cursor when a CURSOR_API_KEY is set, otherwise keeps the Account default",
7793
7925
  "- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
7794
7926
  "- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
7795
7927
  "- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
@@ -7804,9 +7936,9 @@ var init_coordinator_prompt = __esm({
7804
7936
  "- get_diff \u2014 compact diff summary",
7805
7937
  "- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
7806
7938
  '- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id',
7807
- "- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
7939
+ "- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
7808
7940
  '- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
7809
- '- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
7941
+ '- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Ready for review.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
7810
7942
  "Process guides:",
7811
7943
  "- Long child jobs (pack, test, deploy, anything that may run more than ~30s): workers always have `/long-running` (Sideboard product skill). Tell them to detach and wait; they may `stop_job` if it hangs or is doing the wrong thing; do not ask the human to poll.",
7812
7944
  "- Recurring multi-item / fan-out: if the child worktree has `.claude/skills/graph-engineering/SKILL.md`, tell the worker to follow it (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch three threads.",
@@ -8075,32 +8207,32 @@ var init_global_workspace = __esm({
8075
8207
  function brightsyConfigPath() {
8076
8208
  const override = process.env.BRIGHTSY_CONFIG?.trim();
8077
8209
  if (override) return override;
8078
- return (0, import_node_path22.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
8210
+ return (0, import_node_path23.join)((0, import_node_os7.homedir)(), ".brightsy", "config.json");
8079
8211
  }
8080
8212
  function loadBrightsyConfig() {
8081
8213
  const path = brightsyConfigPath();
8082
- if (!(0, import_node_fs19.existsSync)(path)) {
8214
+ if (!(0, import_node_fs20.existsSync)(path)) {
8083
8215
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
8084
8216
  }
8085
- const raw = JSON.parse((0, import_node_fs19.readFileSync)(path, "utf8"));
8217
+ const raw = JSON.parse((0, import_node_fs20.readFileSync)(path, "utf8"));
8086
8218
  if (!raw.access_token || !raw.account_id) {
8087
8219
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
8088
8220
  }
8089
8221
  return raw;
8090
8222
  }
8091
8223
  function saveBrightsyConfig(cfg) {
8092
- (0, import_node_fs19.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
8224
+ (0, import_node_fs20.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
8093
8225
  `, {
8094
8226
  mode: 384
8095
8227
  });
8096
8228
  }
8097
- var import_node_fs19, import_node_os7, import_node_path22;
8229
+ var import_node_fs20, import_node_os7, import_node_path23;
8098
8230
  var init_config = __esm({
8099
8231
  "src/brightsy/config.ts"() {
8100
8232
  "use strict";
8101
- import_node_fs19 = require("fs");
8233
+ import_node_fs20 = require("fs");
8102
8234
  import_node_os7 = require("os");
8103
- import_node_path22 = require("path");
8235
+ import_node_path23 = require("path");
8104
8236
  }
8105
8237
  });
8106
8238
 
@@ -8114,17 +8246,24 @@ var init_accounts = __esm({
8114
8246
  });
8115
8247
 
8116
8248
  // src/http/fetch.ts
8249
+ function tlsIssuerHint(code, message) {
8250
+ const text7 = `${code ?? ""} ${message}`;
8251
+ return TLS_ISSUER_RE.test(text7) ? TLS_ISSUER_HINT : "";
8252
+ }
8117
8253
  function formatFetchError(err, url) {
8118
8254
  if (!(err instanceof Error)) return `${String(err)} (${url})`;
8119
8255
  const cause = err.cause;
8120
8256
  let detail = "";
8257
+ let hint = tlsIssuerHint(void 0, err.message);
8121
8258
  if (cause instanceof Error) {
8122
8259
  const code = typeof cause.code === "string" ? cause.code : void 0;
8123
8260
  detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
8261
+ hint = tlsIssuerHint(code, `${err.message} ${cause.message}`) || hint;
8124
8262
  } else if (cause != null) {
8125
8263
  detail = ` [${String(cause)}]`;
8264
+ hint = tlsIssuerHint(void 0, String(cause)) || hint;
8126
8265
  }
8127
- return `${err.message}${detail} (${url})`;
8266
+ return `${err.message}${detail} (${url})${hint}`;
8128
8267
  }
8129
8268
  async function httpFetch(input, init) {
8130
8269
  const url = typeof input === "string" ? input : input.href;
@@ -8135,11 +8274,13 @@ async function httpFetch(input, init) {
8135
8274
  throw new Error(formatFetchError(err, url));
8136
8275
  }
8137
8276
  }
8138
- var injected;
8277
+ var injected, TLS_ISSUER_RE, TLS_ISSUER_HINT;
8139
8278
  var init_fetch = __esm({
8140
8279
  "src/http/fetch.ts"() {
8141
8280
  "use strict";
8142
8281
  injected = null;
8282
+ TLS_ISSUER_RE = /UNABLE_TO_GET_ISSUER_CERT|UNABLE_TO_VERIFY_LEAF_SIGNATURE|SELF_SIGNED_CERT_IN_CHAIN/i;
8283
+ TLS_ISSUER_HINT = " \u2014 Node rejected the TLS certificate (corporate VPN/proxy CA). Desktop Linear can still work; reconnecting the API key will not fix this.";
8143
8284
  }
8144
8285
  });
8145
8286
 
@@ -8217,22 +8358,22 @@ var init_oauth = __esm({
8217
8358
 
8218
8359
  // src/brightsy/connected-teams.ts
8219
8360
  function storePath4() {
8220
- return (0, import_node_path23.join)(appDataDir(), "brightsy-teams.json");
8361
+ return (0, import_node_path24.join)(appDataDir(), "brightsy-teams.json");
8221
8362
  }
8222
8363
  function readStore4() {
8223
8364
  const path = storePath4();
8224
- if (!(0, import_node_fs20.existsSync)(path)) return [];
8365
+ if (!(0, import_node_fs21.existsSync)(path)) return [];
8225
8366
  try {
8226
- const parsed = JSON.parse((0, import_node_fs20.readFileSync)(path, "utf8"));
8367
+ const parsed = JSON.parse((0, import_node_fs21.readFileSync)(path, "utf8"));
8227
8368
  return Array.isArray(parsed.teams) ? parsed.teams : [];
8228
8369
  } catch {
8229
8370
  return [];
8230
8371
  }
8231
8372
  }
8232
8373
  function writeStore2(teams) {
8233
- (0, import_node_fs20.mkdirSync)(appDataDir(), { recursive: true });
8374
+ (0, import_node_fs21.mkdirSync)(appDataDir(), { recursive: true });
8234
8375
  const path = storePath4();
8235
- (0, import_node_fs20.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
8376
+ (0, import_node_fs21.writeFileSync)(path, `${JSON.stringify({ teams }, null, 2)}
8236
8377
  `, {
8237
8378
  mode: 384
8238
8379
  });
@@ -8338,12 +8479,12 @@ function brightsyMcpServerName(slug) {
8338
8479
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
8339
8480
  return `brightsy_${cleaned || "team"}`;
8340
8481
  }
8341
- var import_node_fs20, import_node_path23;
8482
+ var import_node_fs21, import_node_path24;
8342
8483
  var init_connected_teams = __esm({
8343
8484
  "src/brightsy/connected-teams.ts"() {
8344
8485
  "use strict";
8345
- import_node_fs20 = require("fs");
8346
- import_node_path23 = require("path");
8486
+ import_node_fs21 = require("fs");
8487
+ import_node_path24 = require("path");
8347
8488
  init_paths();
8348
8489
  init_accounts();
8349
8490
  init_config();
@@ -8731,11 +8872,11 @@ async function syncCliForTarget(accountId) {
8731
8872
  }
8732
8873
  applyConnectedTeamToCli(team);
8733
8874
  }
8734
- var import_node_fs21, brightsyAdapter;
8875
+ var import_node_fs22, brightsyAdapter;
8735
8876
  var init_brightsy = __esm({
8736
8877
  "src/agents/brightsy.ts"() {
8737
8878
  "use strict";
8738
- import_node_fs21 = require("fs");
8879
+ import_node_fs22 = require("fs");
8739
8880
  init_run();
8740
8881
  init_connected_teams();
8741
8882
  init_config();
@@ -8750,7 +8891,7 @@ var init_brightsy = __esm({
8750
8891
  async detect() {
8751
8892
  const brightsy = resolveAgentExecutable("brightsy");
8752
8893
  if (brightsy !== "brightsy") {
8753
- if (!(0, import_node_fs21.existsSync)(brightsy)) {
8894
+ if (!(0, import_node_fs22.existsSync)(brightsy)) {
8754
8895
  return {
8755
8896
  agent: "brightsy",
8756
8897
  installed: false,
@@ -9342,43 +9483,43 @@ function electronResourcesPath() {
9342
9483
  function packagedCursorRuntimeDir() {
9343
9484
  const resources = electronResourcesPath();
9344
9485
  if (!resources) return null;
9345
- const dir = (0, import_node_path24.join)(resources, "cursor-runtime");
9346
- if (!(0, import_node_fs22.existsSync)((0, import_node_path24.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
9486
+ const dir = (0, import_node_path25.join)(resources, "cursor-runtime");
9487
+ if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js"))) return null;
9347
9488
  return dir;
9348
9489
  }
9349
9490
  function packagedCursorRunnerPath() {
9350
9491
  const dir = packagedCursorRuntimeDir();
9351
- return dir ? (0, import_node_path24.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
9492
+ return dir ? (0, import_node_path25.join)(dir, "core-dist", "agents", "cursor-runner.js") : null;
9352
9493
  }
9353
9494
  function packagedMcpDir() {
9354
9495
  const resources = electronResourcesPath();
9355
9496
  if (!resources) return null;
9356
- const dir = (0, import_node_path24.join)(resources, "sideboard-mcp");
9357
- if (!(0, import_node_fs22.existsSync)((0, import_node_path24.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
9497
+ const dir = (0, import_node_path25.join)(resources, "sideboard-mcp");
9498
+ if (!(0, import_node_fs23.existsSync)((0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js"))) return null;
9358
9499
  return dir;
9359
9500
  }
9360
9501
  function packagedMcpStdioPath() {
9361
9502
  const dir = packagedMcpDir();
9362
- return dir ? (0, import_node_path24.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
9503
+ return dir ? (0, import_node_path25.join)(dir, "core-dist", "mcp", "run-stdio.js") : null;
9363
9504
  }
9364
9505
  function packagedBundledNodePath() {
9365
9506
  const resources = electronResourcesPath();
9366
9507
  if (!resources) return null;
9367
- const bin = (0, import_node_path24.join)(resources, "node", "bin", "node");
9368
- if (!(0, import_node_fs22.existsSync)(bin)) return null;
9508
+ const bin = (0, import_node_path25.join)(resources, "node", "bin", "node");
9509
+ if (!(0, import_node_fs23.existsSync)(bin)) return null;
9369
9510
  return bin;
9370
9511
  }
9371
9512
  function packagedCursorRipgrepCandidate(platformPkg, binName) {
9372
9513
  const dir = packagedCursorRuntimeDir();
9373
9514
  if (!dir) return null;
9374
- return (0, import_node_path24.join)(dir, "node_modules", platformPkg, "bin", binName);
9515
+ return (0, import_node_path25.join)(dir, "node_modules", platformPkg, "bin", binName);
9375
9516
  }
9376
- var import_node_fs22, import_node_path24;
9517
+ var import_node_fs23, import_node_path25;
9377
9518
  var init_packaged_runtime = __esm({
9378
9519
  "src/agents/packaged-runtime.ts"() {
9379
9520
  "use strict";
9380
- import_node_fs22 = require("fs");
9381
- import_node_path24 = require("path");
9521
+ import_node_fs23 = require("fs");
9522
+ import_node_path25 = require("path");
9382
9523
  }
9383
9524
  });
9384
9525
 
@@ -9398,6 +9539,7 @@ function applyAgentRunnerHeapEnv(env) {
9398
9539
  env.NODE_OPTIONS,
9399
9540
  AGENT_RUNNER_MAX_OLD_SPACE_MB
9400
9541
  );
9542
+ applySystemCaEnv(env);
9401
9543
  }
9402
9544
  function envWithAgentHeap(env) {
9403
9545
  const next = { ...env };
@@ -9412,7 +9554,7 @@ function unpackedAsarPath(filePath) {
9412
9554
  if (!isAsarPath(filePath)) return null;
9413
9555
  const unpacked = filePath.replace(/\.asar(?=[/\\])/, ".asar.unpacked");
9414
9556
  if (unpacked === filePath) return null;
9415
- return (0, import_node_fs23.existsSync)(unpacked) ? unpacked : null;
9557
+ return (0, import_node_fs24.existsSync)(unpacked) ? unpacked : null;
9416
9558
  }
9417
9559
  function nodeReadableScriptPath(scriptPath) {
9418
9560
  return unpackedAsarPath(scriptPath) ?? scriptPath;
@@ -9452,37 +9594,37 @@ function pickPreferredNode(candidates) {
9452
9594
  return best;
9453
9595
  }
9454
9596
  function versionDirNodeBins(root, toBin) {
9455
- if (!(0, import_node_fs23.existsSync)(root)) return [];
9597
+ if (!(0, import_node_fs24.existsSync)(root)) return [];
9456
9598
  try {
9457
- return (0, import_node_fs23.readdirSync)(root).map(toBin);
9599
+ return (0, import_node_fs24.readdirSync)(root).map(toBin);
9458
9600
  } catch {
9459
9601
  return [];
9460
9602
  }
9461
9603
  }
9462
9604
  function defaultNodeBinCandidates(home = (0, import_node_os8.homedir)()) {
9463
9605
  const kegs = ["/opt/homebrew", "/usr/local"].flatMap(
9464
- (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path25.join)(prefix, "opt", `node@${major}`, "bin", "node"))
9606
+ (prefix) => PREFERRED_LTS_MAJORS.map((major) => (0, import_node_path26.join)(prefix, "opt", `node@${major}`, "bin", "node"))
9465
9607
  );
9466
9608
  return [
9467
9609
  ...kegs,
9468
9610
  "/opt/homebrew/bin/node",
9469
9611
  "/usr/local/bin/node",
9470
- (0, import_node_path25.join)(home, ".local/share/fnm/aliases/default/bin/node"),
9471
- (0, import_node_path25.join)(home, ".nvm/current/bin/node"),
9472
- (0, import_node_path25.join)(home, ".volta/bin/node"),
9473
- (0, import_node_path25.join)(home, ".asdf/shims/node"),
9474
- (0, import_node_path25.join)(home, ".local/share/mise/shims/node"),
9612
+ (0, import_node_path26.join)(home, ".local/share/fnm/aliases/default/bin/node"),
9613
+ (0, import_node_path26.join)(home, ".nvm/current/bin/node"),
9614
+ (0, import_node_path26.join)(home, ".volta/bin/node"),
9615
+ (0, import_node_path26.join)(home, ".asdf/shims/node"),
9616
+ (0, import_node_path26.join)(home, ".local/share/mise/shims/node"),
9475
9617
  ...versionDirNodeBins(
9476
- (0, import_node_path25.join)(home, ".nvm", "versions", "node"),
9477
- (name) => (0, import_node_path25.join)(home, ".nvm", "versions", "node", name, "bin", "node")
9618
+ (0, import_node_path26.join)(home, ".nvm", "versions", "node"),
9619
+ (name) => (0, import_node_path26.join)(home, ".nvm", "versions", "node", name, "bin", "node")
9478
9620
  ),
9479
9621
  ...versionDirNodeBins(
9480
- (0, import_node_path25.join)(home, ".local/share/fnm", "node-versions"),
9481
- (name) => (0, import_node_path25.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
9622
+ (0, import_node_path26.join)(home, ".local/share/fnm", "node-versions"),
9623
+ (name) => (0, import_node_path26.join)(home, ".local/share/fnm", "node-versions", name, "installation", "bin", "node")
9482
9624
  ),
9483
9625
  ...versionDirNodeBins(
9484
- (0, import_node_path25.join)(home, ".volta", "tools", "image", "node"),
9485
- (name) => (0, import_node_path25.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
9626
+ (0, import_node_path26.join)(home, ".volta", "tools", "image", "node"),
9627
+ (name) => (0, import_node_path26.join)(home, ".volta", "tools", "image", "node", name, "bin", "node")
9486
9628
  )
9487
9629
  ];
9488
9630
  }
@@ -9491,10 +9633,10 @@ function uniqueExistingNodeBins(paths) {
9491
9633
  const out = [];
9492
9634
  for (const raw of paths) {
9493
9635
  const p = raw.trim();
9494
- if (!p || !(0, import_node_fs23.existsSync)(p) || isElectronLikeCommand(p)) continue;
9636
+ if (!p || !(0, import_node_fs24.existsSync)(p) || isElectronLikeCommand(p)) continue;
9495
9637
  let key = p;
9496
9638
  try {
9497
- key = (0, import_node_fs23.realpathSync)(p);
9639
+ key = (0, import_node_fs24.realpathSync)(p);
9498
9640
  } catch {
9499
9641
  continue;
9500
9642
  }
@@ -9574,14 +9716,15 @@ async function resolveNodeLaunch(scriptPath) {
9574
9716
  env: { ELECTRON_RUN_AS_NODE: "1" }
9575
9717
  };
9576
9718
  }
9577
- var import_node_fs23, import_node_os8, import_node_path25, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
9719
+ var import_node_fs24, import_node_os8, import_node_path26, AGENT_RUNNER_MAX_OLD_SPACE_MB, MAX_OLD_SPACE_FLAG, PREFERRED_LTS_MAJORS;
9578
9720
  var init_node_launch = __esm({
9579
9721
  "src/agents/node-launch.ts"() {
9580
9722
  "use strict";
9581
- import_node_fs23 = require("fs");
9723
+ import_node_fs24 = require("fs");
9582
9724
  import_node_os8 = require("os");
9583
- import_node_path25 = require("path");
9725
+ import_node_path26 = require("path");
9584
9726
  init_nested_electron_env();
9727
+ init_system_ca();
9585
9728
  init_run();
9586
9729
  init_packaged_runtime();
9587
9730
  AGENT_RUNNER_MAX_OLD_SPACE_MB = 8192;
@@ -9681,37 +9824,37 @@ function corePackageDir() {
9681
9824
  try {
9682
9825
  const url = import_meta.url;
9683
9826
  if (typeof url === "string" && url.length > 0) {
9684
- return (0, import_node_path26.dirname)((0, import_node_url.fileURLToPath)(url));
9827
+ return (0, import_node_path27.dirname)((0, import_node_url.fileURLToPath)(url));
9685
9828
  }
9686
9829
  } catch {
9687
9830
  }
9688
9831
  try {
9689
- const req = (0, import_node_module.createRequire)((0, import_node_path26.join)(process.cwd(), "package.json"));
9690
- return (0, import_node_path26.dirname)(req.resolve("@sideboard-ai/core"));
9832
+ const req = (0, import_node_module.createRequire)((0, import_node_path27.join)(process.cwd(), "package.json"));
9833
+ return (0, import_node_path27.dirname)(req.resolve("@sideboard-ai/core"));
9691
9834
  } catch {
9692
9835
  return process.cwd();
9693
9836
  }
9694
9837
  }
9695
9838
  function findSideboardMcpJsEntry() {
9696
9839
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
9697
- if (override && (0, import_node_fs24.existsSync)(override)) return override;
9840
+ if (override && (0, import_node_fs25.existsSync)(override)) return override;
9698
9841
  const packaged = packagedMcpStdioPath();
9699
9842
  if (packaged) return packaged;
9700
9843
  let dir = corePackageDir();
9701
9844
  for (let i = 0; i < 10; i++) {
9702
9845
  const candidates = [
9703
- (0, import_node_path26.join)(dir, "mcp/run-stdio.js"),
9704
- (0, import_node_path26.join)(dir, "mcp/run-stdio.cjs"),
9705
- (0, import_node_path26.join)(dir, "dist/mcp/run-stdio.js"),
9706
- (0, import_node_path26.join)(dir, "dist/mcp/run-stdio.cjs"),
9707
- (0, import_node_path26.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
9708
- (0, import_node_path26.join)(dir, "packages/cli/dist/index.js"),
9709
- (0, import_node_path26.join)(dir, "cli/dist/index.js")
9846
+ (0, import_node_path27.join)(dir, "mcp/run-stdio.js"),
9847
+ (0, import_node_path27.join)(dir, "mcp/run-stdio.cjs"),
9848
+ (0, import_node_path27.join)(dir, "dist/mcp/run-stdio.js"),
9849
+ (0, import_node_path27.join)(dir, "dist/mcp/run-stdio.cjs"),
9850
+ (0, import_node_path27.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
9851
+ (0, import_node_path27.join)(dir, "packages/cli/dist/index.js"),
9852
+ (0, import_node_path27.join)(dir, "cli/dist/index.js")
9710
9853
  ];
9711
9854
  for (const p of candidates) {
9712
- if ((0, import_node_fs24.existsSync)(p) && !isAsarPath(p)) return p;
9855
+ if ((0, import_node_fs25.existsSync)(p) && !isAsarPath(p)) return p;
9713
9856
  }
9714
- const parent = (0, import_node_path26.dirname)(dir);
9857
+ const parent = (0, import_node_path27.dirname)(dir);
9715
9858
  if (parent === dir) break;
9716
9859
  dir = parent;
9717
9860
  }
@@ -9858,19 +10001,19 @@ function writeMcpServersConfig(servers) {
9858
10001
  ...env ? { env } : {}
9859
10002
  };
9860
10003
  }
9861
- const dir = (0, import_node_fs24.mkdtempSync)((0, import_node_path26.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
9862
- const cfgPath = (0, import_node_path26.join)(dir, "mcp.json");
9863
- (0, import_node_fs24.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
10004
+ const dir = (0, import_node_fs25.mkdtempSync)((0, import_node_path27.join)((0, import_node_os9.tmpdir)(), "sideboard-mcp-"));
10005
+ const cfgPath = (0, import_node_path27.join)(dir, "mcp.json");
10006
+ (0, import_node_fs25.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
9864
10007
  return cfgPath;
9865
10008
  }
9866
- var import_node_fs24, import_node_module, import_node_os9, import_node_path26, 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, brightsyMcpCommandCache, BRIGHTSY_WORD;
10009
+ var import_node_fs25, import_node_module, import_node_os9, import_node_path27, 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, brightsyMcpCommandCache, BRIGHTSY_WORD;
9867
10010
  var init_injected_mcp = __esm({
9868
10011
  "src/agents/injected-mcp.ts"() {
9869
10012
  "use strict";
9870
- import_node_fs24 = require("fs");
10013
+ import_node_fs25 = require("fs");
9871
10014
  import_node_module = require("module");
9872
10015
  import_node_os9 = require("os");
9873
- import_node_path26 = require("path");
10016
+ import_node_path27 = require("path");
9874
10017
  import_node_url = require("url");
9875
10018
  init_run();
9876
10019
  init_config();
@@ -10253,11 +10396,11 @@ function parseIssuesJson(raw) {
10253
10396
  }
10254
10397
  return [];
10255
10398
  }
10256
- var import_node_fs25, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
10399
+ var import_node_fs26, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
10257
10400
  var init_claude = __esm({
10258
10401
  "src/agents/claude.ts"() {
10259
10402
  "use strict";
10260
- import_node_fs25 = require("fs");
10403
+ import_node_fs26 = require("fs");
10261
10404
  init_run();
10262
10405
  init_app_settings();
10263
10406
  init_claude_mcp();
@@ -10297,7 +10440,7 @@ var init_claude = __esm({
10297
10440
  async detect() {
10298
10441
  const claude = resolveClaudeExecutable();
10299
10442
  if (claude !== "claude") {
10300
- if (!(0, import_node_fs25.existsSync)(claude)) {
10443
+ if (!(0, import_node_fs26.existsSync)(claude)) {
10301
10444
  return {
10302
10445
  agent: "claude",
10303
10446
  installed: false,
@@ -10556,13 +10699,13 @@ var init_claude = __esm({
10556
10699
  });
10557
10700
 
10558
10701
  // src/agents/user-mcp-config.ts
10559
- var import_node_fs26, import_node_os10, import_node_path27;
10702
+ var import_node_fs27, import_node_os10, import_node_path28;
10560
10703
  var init_user_mcp_config = __esm({
10561
10704
  "src/agents/user-mcp-config.ts"() {
10562
10705
  "use strict";
10563
- import_node_fs26 = require("fs");
10706
+ import_node_fs27 = require("fs");
10564
10707
  import_node_os10 = require("os");
10565
- import_node_path27 = require("path");
10708
+ import_node_path28 = require("path");
10566
10709
  init_paths();
10567
10710
  init_injected_mcp();
10568
10711
  }
@@ -10590,25 +10733,25 @@ function listMcpNamesFromCodexToml(text7) {
10590
10733
  }
10591
10734
  function readJsonObject(path) {
10592
10735
  try {
10593
- return JSON.parse((0, import_node_fs27.readFileSync)(path, "utf8"));
10736
+ return JSON.parse((0, import_node_fs28.readFileSync)(path, "utf8"));
10594
10737
  } catch {
10595
10738
  return {};
10596
10739
  }
10597
10740
  }
10598
10741
  function readText(path) {
10599
10742
  try {
10600
- return (0, import_node_fs27.readFileSync)(path, "utf8");
10743
+ return (0, import_node_fs28.readFileSync)(path, "utf8");
10601
10744
  } catch {
10602
10745
  return "";
10603
10746
  }
10604
10747
  }
10605
10748
  function userCodexConfigPaths(home = (0, import_node_os11.homedir)()) {
10606
- return [(0, import_node_path28.join)(home, ".codex", "config.toml"), (0, import_node_path28.join)(home, ".config", "codex", "config.toml")];
10749
+ return [(0, import_node_path29.join)(home, ".codex", "config.toml"), (0, import_node_path29.join)(home, ".config", "codex", "config.toml")];
10607
10750
  }
10608
10751
  function userOpencodeConfigPaths(home = (0, import_node_os11.homedir)()) {
10609
10752
  return [
10610
- (0, import_node_path28.join)(home, ".config", "opencode", "opencode.json"),
10611
- (0, import_node_path28.join)(home, ".config", "opencode", "opencode.jsonc")
10753
+ (0, import_node_path29.join)(home, ".config", "opencode", "opencode.json"),
10754
+ (0, import_node_path29.join)(home, ".config", "opencode", "opencode.jsonc")
10612
10755
  ];
10613
10756
  }
10614
10757
  function userMcpNamesToDisable(opts) {
@@ -10630,7 +10773,7 @@ function userMcpNamesToDisable(opts) {
10630
10773
  function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
10631
10774
  const names = [];
10632
10775
  for (const path of userCodexConfigPaths(home)) {
10633
- if (!(0, import_node_fs27.existsSync)(path)) continue;
10776
+ if (!(0, import_node_fs28.existsSync)(path)) continue;
10634
10777
  names.push(...listMcpNamesFromCodexToml(readText(path)));
10635
10778
  }
10636
10779
  return names;
@@ -10638,7 +10781,7 @@ function listUserCodexMcpNames(home = (0, import_node_os11.homedir)()) {
10638
10781
  function listUserOpencodeMcpNames(home = (0, import_node_os11.homedir)()) {
10639
10782
  const names = [];
10640
10783
  for (const path of userOpencodeConfigPaths(home)) {
10641
- if (!(0, import_node_fs27.existsSync)(path)) continue;
10784
+ if (!(0, import_node_fs28.existsSync)(path)) continue;
10642
10785
  names.push(...listMcpNamesFromJsonMap(readJsonObject(path), "mcp"));
10643
10786
  }
10644
10787
  return names;
@@ -10651,13 +10794,13 @@ function toCodexDisableUserMcpArgs(names) {
10651
10794
  }
10652
10795
  return args;
10653
10796
  }
10654
- var import_node_fs27, import_node_os11, import_node_path28, import_smol_toml2;
10797
+ var import_node_fs28, import_node_os11, import_node_path29, import_smol_toml2;
10655
10798
  var init_orch_mcp_isolation = __esm({
10656
10799
  "src/agents/orch-mcp-isolation.ts"() {
10657
10800
  "use strict";
10658
- import_node_fs27 = require("fs");
10801
+ import_node_fs28 = require("fs");
10659
10802
  import_node_os11 = require("os");
10660
- import_node_path28 = require("path");
10803
+ import_node_path29 = require("path");
10661
10804
  import_smol_toml2 = require("smol-toml");
10662
10805
  init_user_mcp_config();
10663
10806
  }
@@ -10673,7 +10816,7 @@ async function listCodexModels() {
10673
10816
  if (codex === "codex") {
10674
10817
  const which = await run("which", ["codex"], { reject: false });
10675
10818
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
10676
- } else if (!(0, import_node_fs28.existsSync)(codex)) {
10819
+ } else if (!(0, import_node_fs29.existsSync)(codex)) {
10677
10820
  return FALLBACK_CODEX_MODELS;
10678
10821
  }
10679
10822
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -10708,12 +10851,12 @@ function usageFromCodex(usage) {
10708
10851
  }
10709
10852
  function codexConfigHasNetworkAccess() {
10710
10853
  const candidates = [
10711
- (0, import_node_path29.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
10712
- (0, import_node_path29.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
10854
+ (0, import_node_path30.join)((0, import_node_os12.homedir)(), ".codex", "config.toml"),
10855
+ (0, import_node_path30.join)((0, import_node_os12.homedir)(), ".config", "codex", "config.toml")
10713
10856
  ];
10714
10857
  for (const path of candidates) {
10715
- if (!(0, import_node_fs28.existsSync)(path)) continue;
10716
- const text7 = (0, import_node_fs28.readFileSync)(path, "utf8");
10858
+ if (!(0, import_node_fs29.existsSync)(path)) continue;
10859
+ const text7 = (0, import_node_fs29.readFileSync)(path, "utf8");
10717
10860
  if (/network_access\s*=\s*true/.test(text7)) return true;
10718
10861
  }
10719
10862
  return false;
@@ -10745,21 +10888,21 @@ function asRecord2(value) {
10745
10888
  return void 0;
10746
10889
  }
10747
10890
  function codexLooksAuthenticated() {
10748
- const authPath = (0, import_node_path29.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
10749
- if (!(0, import_node_fs28.existsSync)(authPath)) return false;
10891
+ const authPath = (0, import_node_path30.join)((0, import_node_os12.homedir)(), ".codex", "auth.json");
10892
+ if (!(0, import_node_fs29.existsSync)(authPath)) return false;
10750
10893
  try {
10751
- return (0, import_node_fs28.statSync)(authPath).size > 2;
10894
+ return (0, import_node_fs29.statSync)(authPath).size > 2;
10752
10895
  } catch {
10753
10896
  return false;
10754
10897
  }
10755
10898
  }
10756
- var import_node_fs28, import_node_os12, import_node_path29, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
10899
+ var import_node_fs29, import_node_os12, import_node_path30, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
10757
10900
  var init_codex = __esm({
10758
10901
  "src/agents/codex.ts"() {
10759
10902
  "use strict";
10760
- import_node_fs28 = require("fs");
10903
+ import_node_fs29 = require("fs");
10761
10904
  import_node_os12 = require("os");
10762
- import_node_path29 = require("path");
10905
+ import_node_path30 = require("path");
10763
10906
  init_run();
10764
10907
  init_app_settings();
10765
10908
  init_global_workspace();
@@ -10785,7 +10928,7 @@ var init_codex = __esm({
10785
10928
  async detect() {
10786
10929
  const codex = resolveAgentExecutable("codex");
10787
10930
  if (codex !== "codex") {
10788
- if (!(0, import_node_fs28.existsSync)(codex)) {
10931
+ if (!(0, import_node_fs29.existsSync)(codex)) {
10789
10932
  return {
10790
10933
  agent: "codex",
10791
10934
  installed: false,
@@ -11088,21 +11231,21 @@ function platformRipgrepPackage() {
11088
11231
  }
11089
11232
  function usableRipgrepPath(candidate) {
11090
11233
  const raw = candidate?.trim();
11091
- if (!raw || !(0, import_node_path30.isAbsolute)(raw)) return null;
11234
+ if (!raw || !(0, import_node_path31.isAbsolute)(raw)) return null;
11092
11235
  const readable = nodeReadableScriptPath(raw);
11093
- if (!(0, import_node_fs29.existsSync)(readable) || isAsarPath(readable)) return null;
11236
+ if (!(0, import_node_fs30.existsSync)(readable) || isAsarPath(readable)) return null;
11094
11237
  return readable;
11095
11238
  }
11096
11239
  function walkForBundledRipgrep(startFile) {
11097
11240
  if (!startFile) return null;
11098
11241
  const pkg = platformRipgrepPackage();
11099
11242
  const name = rgBinaryName();
11100
- let dir = (0, import_node_path30.dirname)((0, import_node_path30.resolve)(startFile));
11101
- const root = (0, import_node_path30.parse)(dir).root;
11243
+ let dir = (0, import_node_path31.dirname)((0, import_node_path31.resolve)(startFile));
11244
+ const root = (0, import_node_path31.parse)(dir).root;
11102
11245
  while (dir !== root) {
11103
- const hit = usableRipgrepPath((0, import_node_path30.join)(dir, "node_modules", pkg, "bin", name));
11246
+ const hit = usableRipgrepPath((0, import_node_path31.join)(dir, "node_modules", pkg, "bin", name));
11104
11247
  if (hit) return hit;
11105
- const next = (0, import_node_path30.dirname)(dir);
11248
+ const next = (0, import_node_path31.dirname)(dir);
11106
11249
  if (next === dir) break;
11107
11250
  dir = next;
11108
11251
  }
@@ -11112,7 +11255,7 @@ function requireResolveBundledRipgrep(fromFile) {
11112
11255
  try {
11113
11256
  const req = (0, import_node_module2.createRequire)(fromFile);
11114
11257
  const pkgJson = req.resolve(`${platformRipgrepPackage()}/package.json`);
11115
- return usableRipgrepPath((0, import_node_path30.join)((0, import_node_path30.dirname)(pkgJson), "bin", rgBinaryName()));
11258
+ return usableRipgrepPath((0, import_node_path31.join)((0, import_node_path31.dirname)(pkgJson), "bin", rgBinaryName()));
11116
11259
  } catch {
11117
11260
  return null;
11118
11261
  }
@@ -11134,13 +11277,13 @@ function cursorRipgrepEnv(opts) {
11134
11277
  const path = resolveCursorRipgrepPath(opts);
11135
11278
  return path ? { [RIPGREP_ENV]: path } : {};
11136
11279
  }
11137
- var import_node_fs29, import_node_module2, import_node_path30, RIPGREP_ENV;
11280
+ var import_node_fs30, import_node_module2, import_node_path31, RIPGREP_ENV;
11138
11281
  var init_cursor_ripgrep = __esm({
11139
11282
  "src/agents/cursor-ripgrep.ts"() {
11140
11283
  "use strict";
11141
- import_node_fs29 = require("fs");
11284
+ import_node_fs30 = require("fs");
11142
11285
  import_node_module2 = require("module");
11143
- import_node_path30 = require("path");
11286
+ import_node_path31 = require("path");
11144
11287
  init_node_launch();
11145
11288
  init_packaged_runtime();
11146
11289
  RIPGREP_ENV = "CURSOR_RIPGREP_PATH";
@@ -11153,6 +11296,9 @@ function resolveCursorApiKey() {
11153
11296
  if (fromEnv) return fromEnv;
11154
11297
  return (loadAppSettings().environment.CURSOR_API_KEY || "").trim();
11155
11298
  }
11299
+ function isCursorApiKeyConfigured() {
11300
+ return Boolean(resolveCursorApiKey());
11301
+ }
11156
11302
  async function listCursorModels() {
11157
11303
  const now = Date.now();
11158
11304
  if (cachedModels && now - cachedModels.at < MODEL_CACHE_MS) {
@@ -11178,11 +11324,11 @@ function entryDir() {
11178
11324
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
11179
11325
  if (cjsDir) return cjsDir;
11180
11326
  try {
11181
- return (0, import_node_path31.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
11327
+ return (0, import_node_path32.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
11182
11328
  } catch {
11183
11329
  try {
11184
11330
  const req = (0, import_node_module3.createRequire)(process.cwd() + "/");
11185
- return (0, import_node_path31.dirname)(req.resolve("@sideboard-ai/core"));
11331
+ return (0, import_node_path32.dirname)(req.resolve("@sideboard-ai/core"));
11186
11332
  } catch {
11187
11333
  return process.cwd();
11188
11334
  }
@@ -11193,27 +11339,27 @@ function cursorRunnerPath() {
11193
11339
  if (packaged) return packaged;
11194
11340
  const root = entryDir();
11195
11341
  const candidates = [
11196
- (0, import_node_path31.join)(root, "agents", "cursor-runner.js"),
11197
- (0, import_node_path31.join)(root, "agents", "cursor-runner.cjs"),
11342
+ (0, import_node_path32.join)(root, "agents", "cursor-runner.js"),
11343
+ (0, import_node_path32.join)(root, "agents", "cursor-runner.cjs"),
11198
11344
  // If somehow resolved from package root instead of dist/
11199
- (0, import_node_path31.join)(root, "dist", "agents", "cursor-runner.js"),
11200
- (0, import_node_path31.join)(root, "dist", "agents", "cursor-runner.cjs"),
11345
+ (0, import_node_path32.join)(root, "dist", "agents", "cursor-runner.js"),
11346
+ (0, import_node_path32.join)(root, "dist", "agents", "cursor-runner.cjs"),
11201
11347
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
11202
- (0, import_node_path31.join)(root, "cursor-runner.ts"),
11203
- (0, import_node_path31.join)(root, "src", "agents", "cursor-runner.ts")
11348
+ (0, import_node_path32.join)(root, "cursor-runner.ts"),
11349
+ (0, import_node_path32.join)(root, "src", "agents", "cursor-runner.ts")
11204
11350
  ];
11205
11351
  for (const candidate of candidates) {
11206
- if ((0, import_node_fs30.existsSync)(candidate)) return candidate;
11352
+ if ((0, import_node_fs31.existsSync)(candidate)) return candidate;
11207
11353
  }
11208
11354
  return candidates[0];
11209
11355
  }
11210
- var import_node_fs30, import_node_module3, import_node_path31, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
11356
+ var import_node_fs31, import_node_module3, import_node_path32, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
11211
11357
  var init_cursor = __esm({
11212
11358
  "src/agents/cursor.ts"() {
11213
11359
  "use strict";
11214
- import_node_fs30 = require("fs");
11360
+ import_node_fs31 = require("fs");
11215
11361
  import_node_module3 = require("module");
11216
- import_node_path31 = require("path");
11362
+ import_node_path32 = require("path");
11217
11363
  import_node_url2 = require("url");
11218
11364
  import_sdk = require("@cursor/sdk");
11219
11365
  init_run();
@@ -11365,7 +11511,7 @@ async function listOpencodeModels() {
11365
11511
  if (opencode === "opencode") {
11366
11512
  const which = await run("which", ["opencode"], { reject: false });
11367
11513
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
11368
- } else if (!(0, import_node_fs31.existsSync)(opencode)) {
11514
+ } else if (!(0, import_node_fs32.existsSync)(opencode)) {
11369
11515
  return FALLBACK_OPENCODE_MODELS;
11370
11516
  }
11371
11517
  const listed = await run(opencode, ["models"], { reject: false });
@@ -11395,11 +11541,11 @@ function usageFromOpencode(tokens) {
11395
11541
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
11396
11542
  };
11397
11543
  }
11398
- var import_node_fs31, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
11544
+ var import_node_fs32, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
11399
11545
  var init_opencode = __esm({
11400
11546
  "src/agents/opencode.ts"() {
11401
11547
  "use strict";
11402
- import_node_fs31 = require("fs");
11548
+ import_node_fs32 = require("fs");
11403
11549
  init_run();
11404
11550
  init_app_settings();
11405
11551
  init_global_workspace();
@@ -11427,7 +11573,7 @@ var init_opencode = __esm({
11427
11573
  async detect() {
11428
11574
  const opencode = resolveAgentExecutable("opencode");
11429
11575
  if (opencode !== "opencode") {
11430
- if (!(0, import_node_fs31.existsSync)(opencode)) {
11576
+ if (!(0, import_node_fs32.existsSync)(opencode)) {
11431
11577
  return {
11432
11578
  agent: "opencode",
11433
11579
  installed: false,
@@ -11955,15 +12101,15 @@ var init_agents = __esm({
11955
12101
 
11956
12102
  // src/hook/worktree-pkg-cache.ts
11957
12103
  function worktreePkgCacheRoot(worktreePath) {
11958
- return (0, import_node_path32.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
12104
+ return (0, import_node_path33.join)(worktreePath, WORKTREE_PKG_CACHE_REL);
11959
12105
  }
11960
12106
  function worktreePkgCacheEnv(worktreePath) {
11961
12107
  const root = worktreePkgCacheRoot(worktreePath);
11962
- const store = (0, import_node_path32.join)(root, "pnpm-store");
11963
- const pnpmCache = (0, import_node_path32.join)(root, "pnpm");
11964
- const npmCache = (0, import_node_path32.join)(root, "npm");
11965
- const nodeGyp = (0, import_node_path32.join)(root, "node-gyp");
11966
- const electron = (0, import_node_path32.join)(root, "electron");
12108
+ const store = (0, import_node_path33.join)(root, "pnpm-store");
12109
+ const pnpmCache = (0, import_node_path33.join)(root, "pnpm");
12110
+ const npmCache = (0, import_node_path33.join)(root, "npm");
12111
+ const nodeGyp = (0, import_node_path33.join)(root, "node-gyp");
12112
+ const electron = (0, import_node_path33.join)(root, "electron");
11967
12113
  return {
11968
12114
  npm_config_store_dir: store,
11969
12115
  PNPM_STORE_DIR: store,
@@ -11985,8 +12131,8 @@ function fillGroup(env, keys, values) {
11985
12131
  }
11986
12132
  }
11987
12133
  function ensureWorktreePkgCacheDirs(worktreePath) {
11988
- if (!(0, import_node_fs32.existsSync)(worktreePath)) return;
11989
- (0, import_node_fs32.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
12134
+ if (!(0, import_node_fs33.existsSync)(worktreePath)) return;
12135
+ (0, import_node_fs33.mkdirSync)(worktreePkgCacheRoot(worktreePath), { recursive: true });
11990
12136
  }
11991
12137
  function applyWorktreePkgCacheEnv(env, worktreePath) {
11992
12138
  const cwd = worktreePath.trim();
@@ -11999,12 +12145,12 @@ function applyWorktreePkgCacheEnv(env, worktreePath) {
11999
12145
  fillGroup(env, ["electron_config_cache"], next);
12000
12146
  ensureWorktreePkgCacheDirs(cwd);
12001
12147
  }
12002
- var import_node_fs32, import_node_path32, WORKTREE_PKG_CACHE_REL;
12148
+ var import_node_fs33, import_node_path33, WORKTREE_PKG_CACHE_REL;
12003
12149
  var init_worktree_pkg_cache = __esm({
12004
12150
  "src/hook/worktree-pkg-cache.ts"() {
12005
12151
  "use strict";
12006
- import_node_fs32 = require("fs");
12007
- import_node_path32 = require("path");
12152
+ import_node_fs33 = require("fs");
12153
+ import_node_path33 = require("path");
12008
12154
  WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
12009
12155
  }
12010
12156
  });
@@ -12325,6 +12471,8 @@ function agentGitPrompt(action, opts) {
12325
12471
  const named = base ? ` (${base})` : "";
12326
12472
  return `Merge the remote branch${named} into your branch and resolve conflicts. Then, commit and push your changes.`;
12327
12473
  }
12474
+ case "ready-for-review":
12475
+ return "Ready for review.";
12328
12476
  case "merge":
12329
12477
  return "Merge PR.";
12330
12478
  }
@@ -12339,6 +12487,8 @@ function gitActionExpansion(action, base) {
12339
12487
  return "Commit, push, then `gh pr create --web -R <origin-owner/name>`.";
12340
12488
  case "resolve-conflicts":
12341
12489
  return `Fetch the PR base${base ? ` (\`${base}\`)` : ""}, merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
12490
+ case "ready-for-review":
12491
+ return "This phrase is the explicit ask to mark this thread's draft pull request ready for review on GitHub (`gh pr ready -R <origin-owner/name>` or `gh pr ready`). Update title/body if the purpose drifted. Do not merge.";
12342
12492
  case "merge":
12343
12493
  return "This phrase is the explicit ask to merge this thread's open pull request on GitHub. If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.";
12344
12494
  }
@@ -12381,6 +12531,7 @@ var init_agent_git_actions = __esm({
12381
12531
  "create-draft",
12382
12532
  "create-web",
12383
12533
  "resolve-conflicts",
12534
+ "ready-for-review",
12384
12535
  "merge"
12385
12536
  ];
12386
12537
  RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
@@ -13109,21 +13260,21 @@ function shouldRefreshReviewRequestTemplate(content) {
13109
13260
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
13110
13261
  }
13111
13262
  function readTextIfPresent(abs) {
13112
- if (!(0, import_node_fs33.existsSync)(abs)) return null;
13263
+ if (!(0, import_node_fs34.existsSync)(abs)) return null;
13113
13264
  try {
13114
- const content = (0, import_node_fs33.readFileSync)(abs, "utf8");
13265
+ const content = (0, import_node_fs34.readFileSync)(abs, "utf8");
13115
13266
  return content.trim() ? content : null;
13116
13267
  } catch {
13117
13268
  return null;
13118
13269
  }
13119
13270
  }
13120
13271
  function readLocalGuidelines(worktreePath) {
13121
- const localAbs = (0, import_node_path33.join)(worktreePath, REVIEW_REQUEST_PATH);
13272
+ const localAbs = (0, import_node_path34.join)(worktreePath, REVIEW_REQUEST_PATH);
13122
13273
  const localContent = readTextIfPresent(localAbs);
13123
13274
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
13124
13275
  return { path: REVIEW_REQUEST_PATH, content: localContent };
13125
13276
  }
13126
- const legacyAbs = (0, import_node_path33.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
13277
+ const legacyAbs = (0, import_node_path34.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
13127
13278
  const legacyContent = readTextIfPresent(legacyAbs);
13128
13279
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
13129
13280
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -13147,27 +13298,27 @@ function contextGuidelines(content, source) {
13147
13298
  };
13148
13299
  }
13149
13300
  function writeContextGuidelines(worktreePath, content) {
13150
- const abs = (0, import_node_path33.join)(worktreePath, CONTEXT_REVIEW_PATH);
13151
- (0, import_node_fs33.mkdirSync)((0, import_node_path33.dirname)(abs), { recursive: true });
13301
+ const abs = (0, import_node_path34.join)(worktreePath, CONTEXT_REVIEW_PATH);
13302
+ (0, import_node_fs34.mkdirSync)((0, import_node_path34.dirname)(abs), { recursive: true });
13152
13303
  const body = content.endsWith("\n") ? content : `${content}
13153
13304
  `;
13154
- (0, import_node_fs33.writeFileSync)(abs, body, "utf8");
13305
+ (0, import_node_fs34.writeFileSync)(abs, body, "utf8");
13155
13306
  return body;
13156
13307
  }
13157
13308
  function readSideboardReview(worktreePath, repoPath) {
13158
- const fromWorktree = readTextIfPresent((0, import_node_path33.join)(worktreePath, REPO_REVIEW_PATH));
13309
+ const fromWorktree = readTextIfPresent((0, import_node_path34.join)(worktreePath, REPO_REVIEW_PATH));
13159
13310
  if (fromWorktree) return fromWorktree;
13160
13311
  const repo = repoPath?.replace(/\/+$/, "");
13161
13312
  const wt = worktreePath.replace(/\/+$/, "");
13162
13313
  if (!repo || repo === wt) return null;
13163
- return readTextIfPresent((0, import_node_path33.join)(repo, REPO_REVIEW_PATH));
13314
+ return readTextIfPresent((0, import_node_path34.join)(repo, REPO_REVIEW_PATH));
13164
13315
  }
13165
13316
  function ensureReviewGuidelinesFile(worktreePath, repoPath) {
13166
- const skillContent = readTextIfPresent((0, import_node_path33.join)(worktreePath, REVIEW_SKILL_PATH));
13317
+ const skillContent = readTextIfPresent((0, import_node_path34.join)(worktreePath, REVIEW_SKILL_PATH));
13167
13318
  if (skillContent) {
13168
13319
  return { ...skillGuidelines(skillContent, "skill"), wrote: false };
13169
13320
  }
13170
- const contextContent = readTextIfPresent((0, import_node_path33.join)(worktreePath, CONTEXT_REVIEW_PATH));
13321
+ const contextContent = readTextIfPresent((0, import_node_path34.join)(worktreePath, CONTEXT_REVIEW_PATH));
13171
13322
  if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
13172
13323
  return { ...contextGuidelines(contextContent, "local"), wrote: false };
13173
13324
  }
@@ -13222,13 +13373,13 @@ async function requestReview(threadRef, send) {
13222
13373
  const started = await send(tab.id, REVIEW_REQUEST_PREFILL);
13223
13374
  return { tab: started, from };
13224
13375
  }
13225
- var import_node_crypto7, import_node_fs33, import_node_path33, 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;
13376
+ var import_node_crypto7, import_node_fs34, import_node_path34, 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;
13226
13377
  var init_request_review = __esm({
13227
13378
  "src/review/request-review.ts"() {
13228
13379
  "use strict";
13229
13380
  import_node_crypto7 = require("crypto");
13230
- import_node_fs33 = require("fs");
13231
- import_node_path33 = require("path");
13381
+ import_node_fs34 = require("fs");
13382
+ import_node_path34 = require("path");
13232
13383
  init_global_workspace();
13233
13384
  init_chat_tabs();
13234
13385
  init_thread_store();
@@ -13254,9 +13405,9 @@ function matchSimpleGlob(pattern, name) {
13254
13405
  return new RegExp(`^${escaped}$`).test(name);
13255
13406
  }
13256
13407
  function readWorktreeInclude(repoPath) {
13257
- const path = (0, import_node_path34.join)(repoPath, ".worktreeinclude");
13258
- if (!(0, import_node_fs34.existsSync)(path)) return [];
13259
- return (0, import_node_fs34.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
13408
+ const path = (0, import_node_path35.join)(repoPath, ".worktreeinclude");
13409
+ if (!(0, import_node_fs35.existsSync)(path)) return [];
13410
+ return (0, import_node_fs35.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
13260
13411
  }
13261
13412
  function resolveFilesToCopy(repoPath) {
13262
13413
  const fromInclude = readWorktreeInclude(repoPath);
@@ -13266,10 +13417,10 @@ function resolveFilesToCopy(repoPath) {
13266
13417
  if (settings?.fileIncludeGlobs?.length) {
13267
13418
  const matched = [];
13268
13419
  try {
13269
- for (const entry of (0, import_node_fs34.readdirSync)(repoPath, { withFileTypes: true })) {
13420
+ for (const entry of (0, import_node_fs35.readdirSync)(repoPath, { withFileTypes: true })) {
13270
13421
  if (!entry.isFile()) continue;
13271
13422
  for (const glob of settings.fileIncludeGlobs) {
13272
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path34.basename)(glob), entry.name)) {
13423
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path35.basename)(glob), entry.name)) {
13273
13424
  matched.push(entry.name);
13274
13425
  break;
13275
13426
  }
@@ -13281,7 +13432,7 @@ function resolveFilesToCopy(repoPath) {
13281
13432
  }
13282
13433
  const defaults = [];
13283
13434
  try {
13284
- for (const entry of (0, import_node_fs34.readdirSync)(repoPath, { withFileTypes: true })) {
13435
+ for (const entry of (0, import_node_fs35.readdirSync)(repoPath, { withFileTypes: true })) {
13285
13436
  if (entry.isFile() && entry.name.startsWith(".env")) {
13286
13437
  defaults.push(entry.name);
13287
13438
  }
@@ -13295,11 +13446,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
13295
13446
  const patterns = resolveFilesToCopy(repoPath);
13296
13447
  const copied = [];
13297
13448
  for (const rel of patterns) {
13298
- const src = (0, import_node_path34.join)(repoPath, rel);
13299
- if (!(0, import_node_fs34.existsSync)(src)) continue;
13300
- const dest = (0, import_node_path34.join)(worktreePath, rel);
13301
- (0, import_node_fs34.mkdirSync)((0, import_node_path34.dirname)(dest), { recursive: true });
13302
- (0, import_node_fs34.copyFileSync)(src, dest);
13449
+ const src = (0, import_node_path35.join)(repoPath, rel);
13450
+ if (!(0, import_node_fs35.existsSync)(src)) continue;
13451
+ const dest = (0, import_node_path35.join)(worktreePath, rel);
13452
+ (0, import_node_fs35.mkdirSync)((0, import_node_path35.dirname)(dest), { recursive: true });
13453
+ (0, import_node_fs35.copyFileSync)(src, dest);
13303
13454
  copied.push(rel);
13304
13455
  }
13305
13456
  return copied;
@@ -13334,7 +13485,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
13334
13485
  const env = stripNestedElectronEnv({
13335
13486
  ...baseEnv ?? process.env
13336
13487
  });
13337
- const name = opts.workspaceName ?? (0, import_node_path34.basename)(opts.worktreePath);
13488
+ const name = opts.workspaceName ?? (0, import_node_path35.basename)(opts.worktreePath);
13338
13489
  const ports = opts.ports ?? [];
13339
13490
  const primary = ports[0];
13340
13491
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -13597,13 +13748,13 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
13597
13748
  done: handle.done
13598
13749
  };
13599
13750
  }
13600
- var import_node_fs34, import_node_net, import_node_path34, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
13751
+ var import_node_fs35, import_node_net, import_node_path35, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
13601
13752
  var init_conductor = __esm({
13602
13753
  "src/hook/conductor.ts"() {
13603
13754
  "use strict";
13604
- import_node_fs34 = require("fs");
13755
+ import_node_fs35 = require("fs");
13605
13756
  import_node_net = require("net");
13606
- import_node_path34 = require("path");
13757
+ import_node_path35 = require("path");
13607
13758
  import_execa4 = require("execa");
13608
13759
  import_node_readline3 = require("readline");
13609
13760
  init_settings();
@@ -13622,7 +13773,7 @@ var init_conductor = __esm({
13622
13773
 
13623
13774
  // src/store/setup-log.ts
13624
13775
  function setupLogPath(threadId) {
13625
- return (0, import_node_path35.join)(threadsDir(), `${threadId}.setup.log.json`);
13776
+ return (0, import_node_path36.join)(threadsDir(), `${threadId}.setup.log.json`);
13626
13777
  }
13627
13778
  function emptySetupLog() {
13628
13779
  return { ...EMPTY };
@@ -13639,7 +13790,7 @@ function persistNow(threadId) {
13639
13790
  const snap = memory.get(threadId);
13640
13791
  if (!snap) return;
13641
13792
  try {
13642
- (0, import_node_fs35.writeFileSync)(setupLogPath(threadId), `${JSON.stringify(snap)}
13793
+ (0, import_node_fs36.writeFileSync)(setupLogPath(threadId), `${JSON.stringify(snap)}
13643
13794
  `, "utf8");
13644
13795
  } catch {
13645
13796
  }
@@ -13656,9 +13807,9 @@ function schedulePersist(threadId) {
13656
13807
  }
13657
13808
  function loadFromDisk(threadId) {
13658
13809
  const path = setupLogPath(threadId);
13659
- if (!(0, import_node_fs35.existsSync)(path)) return null;
13810
+ if (!(0, import_node_fs36.existsSync)(path)) return null;
13660
13811
  try {
13661
- const raw = JSON.parse((0, import_node_fs35.readFileSync)(path, "utf8"));
13812
+ const raw = JSON.parse((0, import_node_fs36.readFileSync)(path, "utf8"));
13662
13813
  return {
13663
13814
  output: typeof raw.output === "string" ? raw.output : "",
13664
13815
  running: Boolean(raw.running),
@@ -13714,12 +13865,12 @@ function finishSetupLog(threadId, exitCode, source) {
13714
13865
  persistNow(threadId);
13715
13866
  return clone(snap);
13716
13867
  }
13717
- var import_node_fs35, import_node_path35, EMPTY, memory, persistTimers;
13868
+ var import_node_fs36, import_node_path36, EMPTY, memory, persistTimers;
13718
13869
  var init_setup_log = __esm({
13719
13870
  "src/store/setup-log.ts"() {
13720
13871
  "use strict";
13721
- import_node_fs35 = require("fs");
13722
- import_node_path35 = require("path");
13872
+ import_node_fs36 = require("fs");
13873
+ import_node_path36 = require("path");
13723
13874
  init_paths();
13724
13875
  EMPTY = {
13725
13876
  output: "",
@@ -13743,9 +13894,9 @@ async function findOrphanWorktrees(repoPaths) {
13743
13894
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
13744
13895
  );
13745
13896
  const homeRoot = sideboardWorkspacesDir();
13746
- if ((0, import_node_fs36.existsSync)(homeRoot)) {
13897
+ if ((0, import_node_fs37.existsSync)(homeRoot)) {
13747
13898
  try {
13748
- for (const entry of (0, import_node_fs36.readdirSync)(homeRoot, { withFileTypes: true })) {
13899
+ for (const entry of (0, import_node_fs37.readdirSync)(homeRoot, { withFileTypes: true })) {
13749
13900
  if (!entry.isDirectory()) continue;
13750
13901
  void entry;
13751
13902
  }
@@ -13755,7 +13906,7 @@ async function findOrphanWorktrees(repoPaths) {
13755
13906
  const orphans = [];
13756
13907
  const seen = /* @__PURE__ */ new Set();
13757
13908
  for (const repoPath of repos) {
13758
- if (!repoPath || !(0, import_node_fs36.existsSync)(repoPath)) continue;
13909
+ if (!repoPath || !(0, import_node_fs37.existsSync)(repoPath)) continue;
13759
13910
  try {
13760
13911
  const wts = await listWorktrees(repoPath);
13761
13912
  for (const wt of wts) {
@@ -13766,7 +13917,7 @@ async function findOrphanWorktrees(repoPaths) {
13766
13917
  seen.add(path);
13767
13918
  let mtimeMs = 0;
13768
13919
  try {
13769
- mtimeMs = (0, import_node_fs36.statSync)(path).mtimeMs;
13920
+ mtimeMs = (0, import_node_fs37.statSync)(path).mtimeMs;
13770
13921
  } catch {
13771
13922
  mtimeMs = 0;
13772
13923
  }
@@ -13776,16 +13927,16 @@ async function findOrphanWorktrees(repoPaths) {
13776
13927
  }
13777
13928
  try {
13778
13929
  const root = worktreesRoot(repoPath);
13779
- if ((0, import_node_fs36.existsSync)(root)) {
13780
- for (const entry of (0, import_node_fs36.readdirSync)(root, { withFileTypes: true })) {
13930
+ if ((0, import_node_fs37.existsSync)(root)) {
13931
+ for (const entry of (0, import_node_fs37.readdirSync)(root, { withFileTypes: true })) {
13781
13932
  if (!entry.isDirectory()) continue;
13782
- const path = (0, import_node_path36.join)(root, entry.name).replace(/\/$/, "");
13933
+ const path = (0, import_node_path37.join)(root, entry.name).replace(/\/$/, "");
13783
13934
  if (known.has(path) || seen.has(path)) continue;
13784
- if (!(0, import_node_fs36.existsSync)((0, import_node_path36.join)(path, ".git"))) continue;
13935
+ if (!(0, import_node_fs37.existsSync)((0, import_node_path37.join)(path, ".git"))) continue;
13785
13936
  seen.add(path);
13786
13937
  let mtimeMs = 0;
13787
13938
  try {
13788
- mtimeMs = (0, import_node_fs36.statSync)(path).mtimeMs;
13939
+ mtimeMs = (0, import_node_fs37.statSync)(path).mtimeMs;
13789
13940
  } catch {
13790
13941
  mtimeMs = Date.now();
13791
13942
  }
@@ -13837,12 +13988,12 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
13837
13988
  const elapsed = Date.now() - Date.parse(last);
13838
13989
  return elapsed >= intervalHours * 36e5;
13839
13990
  }
13840
- var import_node_fs36, import_node_path36;
13991
+ var import_node_fs37, import_node_path37;
13841
13992
  var init_orphan_cleanup = __esm({
13842
13993
  "src/git/orphan-cleanup.ts"() {
13843
13994
  "use strict";
13844
- import_node_fs36 = require("fs");
13845
- import_node_path36 = require("path");
13995
+ import_node_fs37 = require("fs");
13996
+ import_node_path37 = require("path");
13846
13997
  init_worktree();
13847
13998
  init_thread_store();
13848
13999
  init_paths();
@@ -13945,12 +14096,12 @@ async function cloneRepoIntoSideboard(opts) {
13945
14096
  if (!url) throw new Error("Clone URL is required");
13946
14097
  let name = opts.name?.trim();
13947
14098
  if (!name) {
13948
- const leaf = (0, import_node_path37.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
14099
+ const leaf = (0, import_node_path38.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
13949
14100
  name = leaf || "repo";
13950
14101
  }
13951
14102
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
13952
- const dest = (0, import_node_path37.join)(sideboardReposDir(), name);
13953
- if ((0, import_node_fs37.existsSync)(dest)) {
14103
+ const dest = (0, import_node_path38.join)(sideboardReposDir(), name);
14104
+ if ((0, import_node_fs38.existsSync)(dest)) {
13954
14105
  const repoPath2 = await resolveRepoRoot(dest);
13955
14106
  const workspace2 = await ensureWorkspace(repoPath2);
13956
14107
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -13965,12 +14116,12 @@ async function cloneRepoIntoSideboard(opts) {
13965
14116
  const workspace = await ensureWorkspace(repoPath);
13966
14117
  return { repoPath, workspace };
13967
14118
  }
13968
- var import_node_fs37, import_node_path37, import_execa6;
14119
+ var import_node_fs38, import_node_path38, import_execa6;
13969
14120
  var init_clone_repo = __esm({
13970
14121
  "src/git/clone-repo.ts"() {
13971
14122
  "use strict";
13972
- import_node_fs37 = require("fs");
13973
- import_node_path37 = require("path");
14123
+ import_node_fs38 = require("fs");
14124
+ import_node_path38 = require("path");
13974
14125
  import_execa6 = require("execa");
13975
14126
  init_paths();
13976
14127
  init_workspaces2();
@@ -13980,11 +14131,11 @@ var init_clone_repo = __esm({
13980
14131
 
13981
14132
  // src/store/desktop-host.ts
13982
14133
  function desktopHostPidPath() {
13983
- return (0, import_node_path38.join)(appDataDir(), "desktop-host.pid");
14134
+ return (0, import_node_path39.join)(appDataDir(), "desktop-host.pid");
13984
14135
  }
13985
14136
  function readDesktopHostPid() {
13986
14137
  try {
13987
- const pid = Number.parseInt((0, import_node_fs38.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
14138
+ const pid = Number.parseInt((0, import_node_fs39.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
13988
14139
  if (!Number.isFinite(pid) || pid <= 0) return null;
13989
14140
  return pid;
13990
14141
  } catch {
@@ -14010,12 +14161,12 @@ function thisProcessShouldDrainAgentQueues() {
14010
14161
  if (isThisProcessDesktopHost()) return true;
14011
14162
  return !isDesktopHostAlive();
14012
14163
  }
14013
- var import_node_fs38, import_node_path38;
14164
+ var import_node_fs39, import_node_path39;
14014
14165
  var init_desktop_host = __esm({
14015
14166
  "src/store/desktop-host.ts"() {
14016
14167
  "use strict";
14017
- import_node_fs38 = require("fs");
14018
- import_node_path38 = require("path");
14168
+ import_node_fs39 = require("fs");
14169
+ import_node_path39 = require("path");
14019
14170
  init_paths();
14020
14171
  }
14021
14172
  });
@@ -14130,24 +14281,24 @@ function jobTreeAlive(pid) {
14130
14281
  return jobAlive(pid) || processGroupAlive(pid);
14131
14282
  }
14132
14283
  function readIntFile(file) {
14133
- if (!(0, import_node_fs39.existsSync)(file)) return null;
14134
- const n = Number.parseInt((0, import_node_fs39.readFileSync)(file, "utf8").trim(), 10);
14284
+ if (!(0, import_node_fs40.existsSync)(file)) return null;
14285
+ const n = Number.parseInt((0, import_node_fs40.readFileSync)(file, "utf8").trim(), 10);
14135
14286
  return Number.isInteger(n) ? n : null;
14136
14287
  }
14137
14288
  function jobDir(root, id, legacy = false) {
14138
- return (0, import_node_path39.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
14289
+ return (0, import_node_path40.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
14139
14290
  }
14140
14291
  function resolveJobDir(root, id) {
14141
14292
  const modern = jobDir(root, id, false);
14142
- if ((0, import_node_fs39.existsSync)(modern)) return modern;
14293
+ if ((0, import_node_fs40.existsSync)(modern)) return modern;
14143
14294
  const legacy = jobDir(root, id, true);
14144
- if ((0, import_node_fs39.existsSync)(legacy)) return legacy;
14295
+ if ((0, import_node_fs40.existsSync)(legacy)) return legacy;
14145
14296
  return modern;
14146
14297
  }
14147
14298
  function listJobIdsIn(root, rel) {
14148
- const dir = (0, import_node_path39.join)(root, rel);
14149
- if (!(0, import_node_fs39.existsSync)(dir)) return [];
14150
- return (0, import_node_fs39.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
14299
+ const dir = (0, import_node_path40.join)(root, rel);
14300
+ if (!(0, import_node_fs40.existsSync)(dir)) return [];
14301
+ return (0, import_node_fs40.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
14151
14302
  }
14152
14303
  function listRunningDetachedJobs(worktreePath) {
14153
14304
  const root = worktreePath.trim();
@@ -14159,7 +14310,7 @@ function listRunningDetachedJobs(worktreePath) {
14159
14310
  const running = [];
14160
14311
  for (const id of ids) {
14161
14312
  const dir = resolveJobDir(root, id);
14162
- const pid = readIntFile((0, import_node_path39.join)(dir, "pid"));
14313
+ const pid = readIntFile((0, import_node_path40.join)(dir, "pid"));
14163
14314
  if (jobTreeAlive(pid)) running.push(id);
14164
14315
  }
14165
14316
  return running.sort();
@@ -14212,13 +14363,13 @@ function planJobContinue(opts) {
14212
14363
  return { action: "none" };
14213
14364
  }
14214
14365
  function tailProgress(logFile, maxLines = 12) {
14215
- if (!(0, import_node_fs39.existsSync)(logFile)) return "(no log yet)";
14216
- const lines = (0, import_node_fs39.readFileSync)(logFile, "utf8").split("\n");
14366
+ if (!(0, import_node_fs40.existsSync)(logFile)) return "(no log yet)";
14367
+ const lines = (0, import_node_fs40.readFileSync)(logFile, "utf8").split("\n");
14217
14368
  return lines.slice(-maxLines).join("\n");
14218
14369
  }
14219
14370
  function readLogLines(file) {
14220
- if (!(0, import_node_fs39.existsSync)(file)) return [];
14221
- const lines = (0, import_node_fs39.readFileSync)(file, "utf8").split("\n");
14371
+ if (!(0, import_node_fs40.existsSync)(file)) return [];
14372
+ const lines = (0, import_node_fs40.readFileSync)(file, "utf8").split("\n");
14222
14373
  if (lines.length && lines[lines.length - 1] === "") lines.pop();
14223
14374
  return lines;
14224
14375
  }
@@ -14229,15 +14380,15 @@ function takeDelta(logFile, cursorFile) {
14229
14380
  return { delta: lines.slice(start).join("\n"), nextCursor: lines.length };
14230
14381
  }
14231
14382
  function snapshotJob(dir) {
14232
- const pid = readIntFile((0, import_node_path39.join)(dir, "pid"));
14383
+ const pid = readIntFile((0, import_node_path40.join)(dir, "pid"));
14233
14384
  const running = jobTreeAlive(pid);
14234
14385
  return {
14235
14386
  pid,
14236
14387
  running,
14237
- exitCode: readIntFile((0, import_node_path39.join)(dir, "exit")),
14238
- log: (0, import_node_path39.join)(dir, "log"),
14239
- cursor: (0, import_node_path39.join)(dir, "present.cursor"),
14240
- progress: tailProgress((0, import_node_path39.join)(dir, "log"))
14388
+ exitCode: readIntFile((0, import_node_path40.join)(dir, "exit")),
14389
+ log: (0, import_node_path40.join)(dir, "log"),
14390
+ cursor: (0, import_node_path40.join)(dir, "present.cursor"),
14391
+ progress: tailProgress((0, import_node_path40.join)(dir, "log"))
14241
14392
  };
14242
14393
  }
14243
14394
  function toResult(id, snap, extra) {
@@ -14246,8 +14397,8 @@ function toResult(id, snap, extra) {
14246
14397
  const stillRunning = snap.running && !ok;
14247
14398
  const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
14248
14399
  try {
14249
- (0, import_node_fs39.mkdirSync)((0, import_node_path39.dirname)(snap.cursor), { recursive: true });
14250
- (0, import_node_fs39.writeFileSync)(snap.cursor, `${nextCursor}
14400
+ (0, import_node_fs40.mkdirSync)((0, import_node_path40.dirname)(snap.cursor), { recursive: true });
14401
+ (0, import_node_fs40.writeFileSync)(snap.cursor, `${nextCursor}
14251
14402
  `);
14252
14403
  } catch {
14253
14404
  }
@@ -14274,7 +14425,7 @@ async function waitForDetachedJob(cwd, id, opts) {
14274
14425
  const dir = resolveJobDir(root, jobId);
14275
14426
  const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
14276
14427
  const sleep = opts?.sleep ?? sleepMs;
14277
- if (!(0, import_node_fs39.existsSync)(dir)) {
14428
+ if (!(0, import_node_fs40.existsSync)(dir)) {
14278
14429
  return {
14279
14430
  stillRunning: false,
14280
14431
  ok: false,
@@ -14320,10 +14471,10 @@ function killProcessTree(pid, signal) {
14320
14471
  }
14321
14472
  function appendJobLog(logFile, line) {
14322
14473
  try {
14323
- (0, import_node_fs39.mkdirSync)((0, import_node_path39.dirname)(logFile), { recursive: true });
14474
+ (0, import_node_fs40.mkdirSync)((0, import_node_path40.dirname)(logFile), { recursive: true });
14324
14475
  const body = line.endsWith("\n") ? line : `${line}
14325
14476
  `;
14326
- (0, import_node_fs39.appendFileSync)(logFile, body);
14477
+ (0, import_node_fs40.appendFileSync)(logFile, body);
14327
14478
  } catch {
14328
14479
  }
14329
14480
  }
@@ -14333,7 +14484,7 @@ async function stopDetachedJob(cwd, id, opts) {
14333
14484
  const dir = resolveJobDir(root, jobId);
14334
14485
  const sleep = opts?.sleep ?? sleepMs;
14335
14486
  const why = opts?.reason?.trim() ?? "";
14336
- if (!(0, import_node_fs39.existsSync)(dir)) {
14487
+ if (!(0, import_node_fs40.existsSync)(dir)) {
14337
14488
  return {
14338
14489
  stillRunning: false,
14339
14490
  ok: false,
@@ -14369,10 +14520,10 @@ async function stopDetachedJob(cwd, id, opts) {
14369
14520
  killProcessTree(targetPid, "SIGKILL");
14370
14521
  await sleep(100);
14371
14522
  }
14372
- const exitFile = (0, import_node_path39.join)(dir, "exit");
14373
- if (!(0, import_node_fs39.existsSync)(exitFile)) {
14523
+ const exitFile = (0, import_node_path40.join)(dir, "exit");
14524
+ if (!(0, import_node_fs40.existsSync)(exitFile)) {
14374
14525
  try {
14375
- (0, import_node_fs39.writeFileSync)(exitFile, "1\n");
14526
+ (0, import_node_fs40.writeFileSync)(exitFile, "1\n");
14376
14527
  } catch {
14377
14528
  }
14378
14529
  }
@@ -14392,12 +14543,12 @@ async function stopDetachedJob(cwd, id, opts) {
14392
14543
  hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
14393
14544
  };
14394
14545
  }
14395
- var import_node_fs39, import_node_path39, MAX_JOB_CONTINUES, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
14546
+ var import_node_fs40, import_node_path40, MAX_JOB_CONTINUES, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
14396
14547
  var init_wait_for_job = __esm({
14397
14548
  "src/mcp/wait-for-job.ts"() {
14398
14549
  "use strict";
14399
- import_node_fs39 = require("fs");
14400
- import_node_path39 = require("path");
14550
+ import_node_fs40 = require("fs");
14551
+ import_node_path40 = require("path");
14401
14552
  init_workspace_scratch();
14402
14553
  init_wait_for_turn();
14403
14554
  MAX_JOB_CONTINUES = 8;
@@ -15492,7 +15643,7 @@ function reuseLiveThread(input, repoPath, match) {
15492
15643
  }
15493
15644
  async function createThread(input, _onSetupLine) {
15494
15645
  const repoPath = await resolveRepoRoot(input.repoPath);
15495
- if (!(0, import_node_fs40.existsSync)(repoPath)) {
15646
+ if (!(0, import_node_fs41.existsSync)(repoPath)) {
15496
15647
  throw new Error(`Repo not found: ${repoPath}`);
15497
15648
  }
15498
15649
  const reused = reuseLiveThread(input, repoPath, {
@@ -15664,11 +15815,11 @@ async function createThread(input, _onSetupLine) {
15664
15815
  await ensureWorkspace(repoPath);
15665
15816
  return readThread(thread.id) ?? thread;
15666
15817
  }
15667
- var import_node_fs40;
15818
+ var import_node_fs41;
15668
15819
  var init_create = __esm({
15669
15820
  "src/threads/create.ts"() {
15670
15821
  "use strict";
15671
- import_node_fs40 = require("fs");
15822
+ import_node_fs41 = require("fs");
15672
15823
  init_detect();
15673
15824
  init_worktree();
15674
15825
  init_home_board();
@@ -15788,20 +15939,20 @@ function writeTurnLive(threadId, progress) {
15788
15939
  const path = threadLivePath(threadId);
15789
15940
  const tmp = `${path}.${process.pid}.tmp`;
15790
15941
  try {
15791
- (0, import_node_fs41.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
15792
- (0, import_node_fs41.renameSync)(tmp, path);
15942
+ (0, import_node_fs42.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
15943
+ (0, import_node_fs42.renameSync)(tmp, path);
15793
15944
  } catch {
15794
15945
  try {
15795
- (0, import_node_fs41.unlinkSync)(tmp);
15946
+ (0, import_node_fs42.unlinkSync)(tmp);
15796
15947
  } catch {
15797
15948
  }
15798
15949
  }
15799
15950
  }
15800
15951
  function readTurnLive(threadId) {
15801
15952
  const path = threadLivePath(threadId);
15802
- if (!(0, import_node_fs41.existsSync)(path)) return null;
15953
+ if (!(0, import_node_fs42.existsSync)(path)) return null;
15803
15954
  try {
15804
- const raw = JSON.parse((0, import_node_fs41.readFileSync)(path, "utf8"));
15955
+ const raw = JSON.parse((0, import_node_fs42.readFileSync)(path, "utf8"));
15805
15956
  if (!raw || typeof raw.summary !== "string") return null;
15806
15957
  return raw;
15807
15958
  } catch {
@@ -15813,17 +15964,17 @@ function clearTurnLive(threadId) {
15813
15964
  if (buf?.timer) clearTimeout(buf.timer);
15814
15965
  buffers.delete(threadId);
15815
15966
  const path = threadLivePath(threadId);
15816
- if (!(0, import_node_fs41.existsSync)(path)) return;
15967
+ if (!(0, import_node_fs42.existsSync)(path)) return;
15817
15968
  try {
15818
- (0, import_node_fs41.unlinkSync)(path);
15969
+ (0, import_node_fs42.unlinkSync)(path);
15819
15970
  } catch {
15820
15971
  }
15821
15972
  }
15822
- var import_node_fs41, buffers, FLUSH_MS, MAX_PARTS;
15973
+ var import_node_fs42, buffers, FLUSH_MS, MAX_PARTS;
15823
15974
  var init_turn_live = __esm({
15824
15975
  "src/store/turn-live.ts"() {
15825
15976
  "use strict";
15826
- import_node_fs41 = require("fs");
15977
+ import_node_fs42 = require("fs");
15827
15978
  init_message_parts();
15828
15979
  init_paths();
15829
15980
  buffers = /* @__PURE__ */ new Map();
@@ -16040,7 +16191,7 @@ var init_quota_failover = __esm({
16040
16191
  // src/threads/adopt.ts
16041
16192
  function thisModuleFile() {
16042
16193
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
16043
- return cjsFile || process.argv[1] || (0, import_node_path40.join)(process.cwd(), "package.json");
16194
+ return cjsFile || process.argv[1] || (0, import_node_path41.join)(process.cwd(), "package.json");
16044
16195
  }
16045
16196
  function openReadonlySqlite(file) {
16046
16197
  const req = (0, import_node_module4.createRequire)(thisModuleFile());
@@ -16058,21 +16209,21 @@ function mapAgentType(raw) {
16058
16209
  return null;
16059
16210
  }
16060
16211
  function resolveConductorCursorAgentId(workspacePath) {
16061
- if (!workspacePath || !(0, import_node_fs42.existsSync)(CURSOR_SDK_STORE)) return null;
16212
+ if (!workspacePath || !(0, import_node_fs43.existsSync)(CURSOR_SDK_STORE)) return null;
16062
16213
  const normalized = workspacePath.replace(/\/$/, "");
16063
16214
  let best = null;
16064
16215
  let hashes;
16065
16216
  try {
16066
- hashes = (0, import_node_fs42.readdirSync)(CURSOR_SDK_STORE);
16217
+ hashes = (0, import_node_fs43.readdirSync)(CURSOR_SDK_STORE);
16067
16218
  } catch {
16068
16219
  return null;
16069
16220
  }
16070
16221
  for (const hash of hashes) {
16071
- const agentsFile = (0, import_node_path40.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
16072
- if (!(0, import_node_fs42.existsSync)(agentsFile)) continue;
16222
+ const agentsFile = (0, import_node_path41.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
16223
+ if (!(0, import_node_fs43.existsSync)(agentsFile)) continue;
16073
16224
  let text7;
16074
16225
  try {
16075
- text7 = (0, import_node_fs42.readFileSync)(agentsFile, "utf8");
16226
+ text7 = (0, import_node_fs43.readFileSync)(agentsFile, "utf8");
16076
16227
  } catch {
16077
16228
  continue;
16078
16229
  }
@@ -16096,7 +16247,7 @@ function resolveConductorCursorAgentId(workspacePath) {
16096
16247
  return best?.agentId ?? null;
16097
16248
  }
16098
16249
  async function adoptThread(input) {
16099
- if (!(0, import_node_fs42.existsSync)(input.worktreePath)) {
16250
+ if (!(0, import_node_fs43.existsSync)(input.worktreePath)) {
16100
16251
  throw new Error(`Worktree not found: ${input.worktreePath}`);
16101
16252
  }
16102
16253
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -16122,18 +16273,18 @@ async function adoptThread(input) {
16122
16273
  return thread;
16123
16274
  }
16124
16275
  function listConductorWorkspaces() {
16125
- if (!(0, import_node_fs42.existsSync)(CONDUCTOR_DB)) {
16276
+ if (!(0, import_node_fs43.existsSync)(CONDUCTOR_DB)) {
16126
16277
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
16127
16278
  }
16128
- const tmp = (0, import_node_fs42.mkdtempSync)((0, import_node_path40.join)((0, import_node_os13.tmpdir)(), "sideboard-conductor-"));
16129
- const snapshot = (0, import_node_path40.join)(tmp, "conductor.db");
16279
+ const tmp = (0, import_node_fs43.mkdtempSync)((0, import_node_path41.join)((0, import_node_os13.tmpdir)(), "sideboard-conductor-"));
16280
+ const snapshot = (0, import_node_path41.join)(tmp, "conductor.db");
16130
16281
  try {
16131
- (0, import_node_fs42.copyFileSync)(CONDUCTOR_DB, snapshot);
16282
+ (0, import_node_fs43.copyFileSync)(CONDUCTOR_DB, snapshot);
16132
16283
  for (const suffix of ["-wal", "-shm"]) {
16133
16284
  const src = `${CONDUCTOR_DB}${suffix}`;
16134
- if ((0, import_node_fs42.existsSync)(src)) {
16285
+ if ((0, import_node_fs43.existsSync)(src)) {
16135
16286
  try {
16136
- (0, import_node_fs42.copyFileSync)(src, `${snapshot}${suffix}`);
16287
+ (0, import_node_fs43.copyFileSync)(src, `${snapshot}${suffix}`);
16137
16288
  } catch {
16138
16289
  }
16139
16290
  }
@@ -16209,22 +16360,22 @@ function listConductorWorkspaces() {
16209
16360
  db.close();
16210
16361
  }
16211
16362
  } finally {
16212
- (0, import_node_fs42.rmSync)(tmp, { recursive: true, force: true });
16363
+ (0, import_node_fs43.rmSync)(tmp, { recursive: true, force: true });
16213
16364
  }
16214
16365
  }
16215
16366
  function importConductorWorkspace(workspaceId) {
16216
- if (!(0, import_node_fs42.existsSync)(CONDUCTOR_DB)) {
16367
+ if (!(0, import_node_fs43.existsSync)(CONDUCTOR_DB)) {
16217
16368
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
16218
16369
  }
16219
- const tmp = (0, import_node_fs42.mkdtempSync)((0, import_node_path40.join)((0, import_node_os13.tmpdir)(), "sideboard-conductor-"));
16220
- const snapshot = (0, import_node_path40.join)(tmp, "conductor.db");
16370
+ const tmp = (0, import_node_fs43.mkdtempSync)((0, import_node_path41.join)((0, import_node_os13.tmpdir)(), "sideboard-conductor-"));
16371
+ const snapshot = (0, import_node_path41.join)(tmp, "conductor.db");
16221
16372
  try {
16222
- (0, import_node_fs42.copyFileSync)(CONDUCTOR_DB, snapshot);
16373
+ (0, import_node_fs43.copyFileSync)(CONDUCTOR_DB, snapshot);
16223
16374
  for (const suffix of ["-wal", "-shm"]) {
16224
16375
  const src = `${CONDUCTOR_DB}${suffix}`;
16225
- if ((0, import_node_fs42.existsSync)(src)) {
16376
+ if ((0, import_node_fs43.existsSync)(src)) {
16226
16377
  try {
16227
- (0, import_node_fs42.copyFileSync)(src, `${snapshot}${suffix}`);
16378
+ (0, import_node_fs43.copyFileSync)(src, `${snapshot}${suffix}`);
16228
16379
  } catch {
16229
16380
  }
16230
16381
  }
@@ -16242,7 +16393,7 @@ function importConductorWorkspace(workspaceId) {
16242
16393
  ).get(workspaceId);
16243
16394
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
16244
16395
  const worktreePath = String(row.workspacePath);
16245
- if (!(0, import_node_fs42.existsSync)(worktreePath)) {
16396
+ if (!(0, import_node_fs43.existsSync)(worktreePath)) {
16246
16397
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
16247
16398
  }
16248
16399
  let sessionId = null;
@@ -16282,7 +16433,7 @@ function importConductorWorkspace(workspaceId) {
16282
16433
  }
16283
16434
  let repoPath = worktreePath;
16284
16435
  try {
16285
- repoPath = (0, import_node_child_process3.execFileSync)("git", ["rev-parse", "--show-toplevel"], {
16436
+ repoPath = (0, import_node_child_process4.execFileSync)("git", ["rev-parse", "--show-toplevel"], {
16286
16437
  cwd: worktreePath,
16287
16438
  encoding: "utf8"
16288
16439
  }).trim();
@@ -16305,31 +16456,31 @@ function importConductorWorkspace(workspaceId) {
16305
16456
  db.close();
16306
16457
  }
16307
16458
  } finally {
16308
- (0, import_node_fs42.rmSync)(tmp, { recursive: true, force: true });
16459
+ (0, import_node_fs43.rmSync)(tmp, { recursive: true, force: true });
16309
16460
  }
16310
16461
  }
16311
16462
  async function importConductorWorkspaceAsync(workspaceId) {
16312
16463
  return importConductorWorkspace(workspaceId);
16313
16464
  }
16314
- var import_node_child_process3, import_node_fs42, import_node_os13, import_node_path40, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
16465
+ var import_node_child_process4, import_node_fs43, import_node_os13, import_node_path41, import_node_module4, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
16315
16466
  var init_adopt = __esm({
16316
16467
  "src/threads/adopt.ts"() {
16317
16468
  "use strict";
16318
- import_node_child_process3 = require("child_process");
16319
- import_node_fs42 = require("fs");
16469
+ import_node_child_process4 = require("child_process");
16470
+ import_node_fs43 = require("fs");
16320
16471
  import_node_os13 = require("os");
16321
- import_node_path40 = require("path");
16472
+ import_node_path41 = require("path");
16322
16473
  import_node_module4 = require("module");
16323
16474
  init_worktree();
16324
16475
  init_thread_store();
16325
- CONDUCTOR_APP_SUPPORT = (0, import_node_path40.join)(
16476
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path41.join)(
16326
16477
  process.env.HOME ?? "",
16327
16478
  "Library",
16328
16479
  "Application Support",
16329
16480
  "com.conductor.app"
16330
16481
  );
16331
- CONDUCTOR_DB = (0, import_node_path40.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
16332
- CURSOR_SDK_STORE = (0, import_node_path40.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
16482
+ CONDUCTOR_DB = (0, import_node_path41.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
16483
+ CURSOR_SDK_STORE = (0, import_node_path41.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
16333
16484
  }
16334
16485
  });
16335
16486
 
@@ -16396,7 +16547,7 @@ async function openStackLayer(input, _onSetupLine) {
16396
16547
  let createdWorktree = false;
16397
16548
  const trees = await listWorktrees(repoPath);
16398
16549
  const checkedOut = trees.find((w) => w.branch === branchName);
16399
- if (checkedOut?.path && (0, import_node_fs43.existsSync)(checkedOut.path)) {
16550
+ if (checkedOut?.path && (0, import_node_fs44.existsSync)(checkedOut.path)) {
16400
16551
  if (input.reuseExistingWorktree !== false) {
16401
16552
  worktreePath = checkedOut.path;
16402
16553
  } else {
@@ -16538,7 +16689,7 @@ async function initStackFromThread(input, onSetupLine) {
16538
16689
  async function createPrStack(input, onSetupLine) {
16539
16690
  await requireAgent(input.agent);
16540
16691
  const repoPath = await resolveRepoRoot(input.repoPath);
16541
- if (!(0, import_node_fs43.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
16692
+ if (!(0, import_node_fs44.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
16542
16693
  if (!input.branches.length) throw new Error("At least one branch name required");
16543
16694
  const status = await detectGhStack(repoPath);
16544
16695
  if (!status.available) throw new Error(status.reason);
@@ -16605,7 +16756,7 @@ async function createPrStack(input, onSetupLine) {
16605
16756
  }
16606
16757
  }
16607
16758
  const claimed = new Set(threads.map((t) => t.worktreePath));
16608
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs43.existsSync)(bootstrap.worktreePath)) {
16759
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs44.existsSync)(bootstrap.worktreePath)) {
16609
16760
  try {
16610
16761
  await removeWorktree(repoPath, bootstrap.worktreePath, {
16611
16762
  deleteBranch: bootstrap.branchName
@@ -16615,11 +16766,11 @@ async function createPrStack(input, onSetupLine) {
16615
16766
  }
16616
16767
  return { stack, threads, createdThreadIds };
16617
16768
  }
16618
- var import_node_fs43;
16769
+ var import_node_fs44;
16619
16770
  var init_stack_layers = __esm({
16620
16771
  "src/threads/stack-layers.ts"() {
16621
16772
  "use strict";
16622
- import_node_fs43 = require("fs");
16773
+ import_node_fs44 = require("fs");
16623
16774
  init_detect();
16624
16775
  init_run();
16625
16776
  init_stack();
@@ -16632,7 +16783,7 @@ var init_stack_layers = __esm({
16632
16783
 
16633
16784
  // src/diff/diff.ts
16634
16785
  async function inspectGitWorktree(worktreePath) {
16635
- if (!worktreePath || !(0, import_node_fs44.existsSync)(worktreePath)) return "missing_worktree";
16786
+ if (!worktreePath || !(0, import_node_fs45.existsSync)(worktreePath)) return "missing_worktree";
16636
16787
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
16637
16788
  reject: false
16638
16789
  });
@@ -16640,7 +16791,7 @@ async function inspectGitWorktree(worktreePath) {
16640
16791
  return "ok";
16641
16792
  }
16642
16793
  async function initializeGitRepository(worktreePath) {
16643
- if (!worktreePath || !(0, import_node_fs44.existsSync)(worktreePath)) {
16794
+ if (!worktreePath || !(0, import_node_fs45.existsSync)(worktreePath)) {
16644
16795
  throw new Error("Worktree not found");
16645
16796
  }
16646
16797
  const status = await inspectGitWorktree(worktreePath);
@@ -16774,11 +16925,11 @@ new file mode 100644
16774
16925
  };
16775
16926
  }
16776
16927
  async function untrackedPatch(worktreePath, path, maxHunk) {
16777
- const abs = (0, import_node_path41.join)(worktreePath, path);
16928
+ const abs = (0, import_node_path42.join)(worktreePath, path);
16778
16929
  try {
16779
- const st = (0, import_node_fs44.statSync)(abs);
16930
+ const st = (0, import_node_fs45.statSync)(abs);
16780
16931
  if (st.isFile() && st.size > maxHunk) {
16781
- const buf = (0, import_node_fs44.readFileSync)(abs).subarray(0, maxHunk);
16932
+ const buf = (0, import_node_fs45.readFileSync)(abs).subarray(0, maxHunk);
16782
16933
  return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
16783
16934
  }
16784
16935
  } catch {
@@ -17267,8 +17418,8 @@ function isImageRelativePath(relativePath) {
17267
17418
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
17268
17419
  assertSafeRelativePath(relativePath);
17269
17420
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
17270
- const abs = (0, import_node_path41.join)(worktreePath, relativePath);
17271
- const st = (0, import_node_fs44.statSync)(abs);
17421
+ const abs = (0, import_node_path42.join)(worktreePath, relativePath);
17422
+ const st = (0, import_node_fs45.statSync)(abs);
17272
17423
  if (!st.isFile()) {
17273
17424
  throw new Error(`Not a file: ${relativePath}`);
17274
17425
  }
@@ -17277,7 +17428,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
17277
17428
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
17278
17429
  );
17279
17430
  }
17280
- const buf = (0, import_node_fs44.readFileSync)(abs);
17431
+ const buf = (0, import_node_fs45.readFileSync)(abs);
17281
17432
  return {
17282
17433
  path: relativePath,
17283
17434
  contentBase64: buf.toString("base64"),
@@ -17287,12 +17438,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
17287
17438
  function readWorktreeFile(worktreePath, relativePath, opts) {
17288
17439
  assertSafeRelativePath(relativePath);
17289
17440
  const maxBytes = opts?.maxBytes ?? 2e5;
17290
- const abs = (0, import_node_path41.join)(worktreePath, relativePath);
17291
- const st = (0, import_node_fs44.statSync)(abs);
17441
+ const abs = (0, import_node_path42.join)(worktreePath, relativePath);
17442
+ const st = (0, import_node_fs45.statSync)(abs);
17292
17443
  if (!st.isFile()) {
17293
17444
  throw new Error(`Not a file: ${relativePath}`);
17294
17445
  }
17295
- const buf = (0, import_node_fs44.readFileSync)(abs);
17446
+ const buf = (0, import_node_fs45.readFileSync)(abs);
17296
17447
  if (isImageRelativePath(relativePath)) {
17297
17448
  const maxImageBytes = Math.max(maxBytes, 15e6);
17298
17449
  const truncated2 = buf.length > maxImageBytes;
@@ -17335,9 +17486,9 @@ function assertSafeRelativePath(relativePath) {
17335
17486
  }
17336
17487
  function writeWorktreeFile(worktreePath, relativePath, content) {
17337
17488
  assertSafeRelativePath(relativePath);
17338
- const abs = (0, import_node_path41.join)(worktreePath, relativePath);
17339
- (0, import_node_fs44.mkdirSync)((0, import_node_path41.dirname)(abs), { recursive: true });
17340
- (0, import_node_fs44.writeFileSync)(abs, content, "utf8");
17489
+ const abs = (0, import_node_path42.join)(worktreePath, relativePath);
17490
+ (0, import_node_fs45.mkdirSync)((0, import_node_path42.dirname)(abs), { recursive: true });
17491
+ (0, import_node_fs45.writeFileSync)(abs, content, "utf8");
17341
17492
  return { path: relativePath };
17342
17493
  }
17343
17494
  async function getDiffSummary(worktreePath, repoPath, opts) {
@@ -17354,12 +17505,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
17354
17505
  truncated: full.files.length > maxFiles
17355
17506
  };
17356
17507
  }
17357
- var import_node_fs44, import_node_path41, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
17508
+ var import_node_fs45, import_node_path42, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
17358
17509
  var init_diff = __esm({
17359
17510
  "src/diff/diff.ts"() {
17360
17511
  "use strict";
17361
- import_node_fs44 = require("fs");
17362
- import_node_path41 = require("path");
17512
+ import_node_fs45 = require("fs");
17513
+ import_node_path42 = require("path");
17363
17514
  init_run();
17364
17515
  init_worktree();
17365
17516
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -17635,7 +17786,7 @@ function parseFrontmatter(content) {
17635
17786
  }
17636
17787
  function readSkill(skillMd, source) {
17637
17788
  try {
17638
- const content = (0, import_node_fs45.readFileSync)(skillMd, "utf8");
17789
+ const content = (0, import_node_fs46.readFileSync)(skillMd, "utf8");
17639
17790
  const { name: fmName, description } = parseFrontmatter(content);
17640
17791
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
17641
17792
  const name = fmName || dirName;
@@ -17654,19 +17805,19 @@ function readSkill(skillMd, source) {
17654
17805
  }
17655
17806
  }
17656
17807
  function scanSkillsDir(dir, source, out) {
17657
- if (!(0, import_node_fs45.existsSync)(dir)) return;
17808
+ if (!(0, import_node_fs46.existsSync)(dir)) return;
17658
17809
  let entries;
17659
17810
  try {
17660
- entries = (0, import_node_fs45.readdirSync)(dir);
17811
+ entries = (0, import_node_fs46.readdirSync)(dir);
17661
17812
  } catch {
17662
17813
  return;
17663
17814
  }
17664
17815
  for (const entry of entries) {
17665
17816
  if (entry.startsWith(".")) continue;
17666
- const skillMd = (0, import_node_path42.join)(dir, entry, "SKILL.md");
17667
- if (!(0, import_node_fs45.existsSync)(skillMd)) continue;
17817
+ const skillMd = (0, import_node_path43.join)(dir, entry, "SKILL.md");
17818
+ if (!(0, import_node_fs46.existsSync)(skillMd)) continue;
17668
17819
  try {
17669
- if (!(0, import_node_fs45.statSync)(skillMd).isFile()) continue;
17820
+ if (!(0, import_node_fs46.statSync)(skillMd).isFile()) continue;
17670
17821
  } catch {
17671
17822
  continue;
17672
17823
  }
@@ -17675,24 +17826,24 @@ function scanSkillsDir(dir, source, out) {
17675
17826
  }
17676
17827
  }
17677
17828
  function scanClaudePluginSkills(pluginsRoot, out) {
17678
- if (!(0, import_node_fs45.existsSync)(pluginsRoot)) return;
17829
+ if (!(0, import_node_fs46.existsSync)(pluginsRoot)) return;
17679
17830
  const walk = (dir, depth, lookingForSkillsDir) => {
17680
17831
  if (depth > 7) return;
17681
17832
  let entries;
17682
17833
  try {
17683
- entries = (0, import_node_fs45.readdirSync)(dir);
17834
+ entries = (0, import_node_fs46.readdirSync)(dir);
17684
17835
  } catch {
17685
17836
  return;
17686
17837
  }
17687
17838
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
17688
- const skill = readSkill((0, import_node_path42.join)(dir, "SKILL.md"), "cli");
17839
+ const skill = readSkill((0, import_node_path43.join)(dir, "SKILL.md"), "cli");
17689
17840
  if (skill) out.push(skill);
17690
17841
  }
17691
17842
  for (const entry of entries) {
17692
17843
  if (entry === "node_modules" || entry === ".git") continue;
17693
- const full = (0, import_node_path42.join)(dir, entry);
17844
+ const full = (0, import_node_path43.join)(dir, entry);
17694
17845
  try {
17695
- if (!(0, import_node_fs45.statSync)(full).isDirectory()) continue;
17846
+ if (!(0, import_node_fs46.statSync)(full).isDirectory()) continue;
17696
17847
  } catch {
17697
17848
  continue;
17698
17849
  }
@@ -17710,17 +17861,17 @@ function discoverSkills(worktreePath) {
17710
17861
  const home = (0, import_node_os14.homedir)();
17711
17862
  const collected = [];
17712
17863
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
17713
- scanSkillsDir((0, import_node_path42.join)(worktreePath, rel), "workspace", collected);
17864
+ scanSkillsDir((0, import_node_path43.join)(worktreePath, rel), "workspace", collected);
17714
17865
  }
17715
17866
  for (const abs of [
17716
- (0, import_node_path42.join)(home, ".claude/skills"),
17717
- (0, import_node_path42.join)(home, ".cursor/skills"),
17718
- (0, import_node_path42.join)(home, ".sideboard/skills"),
17719
- (0, import_node_path42.join)(home, ".brightsy/skills")
17867
+ (0, import_node_path43.join)(home, ".claude/skills"),
17868
+ (0, import_node_path43.join)(home, ".cursor/skills"),
17869
+ (0, import_node_path43.join)(home, ".sideboard/skills"),
17870
+ (0, import_node_path43.join)(home, ".brightsy/skills")
17720
17871
  ]) {
17721
17872
  scanSkillsDir(abs, "user", collected);
17722
17873
  }
17723
- scanClaudePluginSkills((0, import_node_path42.join)(home, ".claude/plugins"), collected);
17874
+ scanClaudePluginSkills((0, import_node_path43.join)(home, ".claude/plugins"), collected);
17724
17875
  collected.push(...bundledSkills());
17725
17876
  const rank = {
17726
17877
  workspace: 0,
@@ -17746,7 +17897,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
17746
17897
  \u2026(truncated)` : body;
17747
17898
  }
17748
17899
  }
17749
- const raw = (0, import_node_fs45.readFileSync)(skillPath, "utf8");
17900
+ const raw = (0, import_node_fs46.readFileSync)(skillPath, "utf8");
17750
17901
  if (raw.startsWith("---")) {
17751
17902
  const end = raw.indexOf("\n---", 3);
17752
17903
  if (end >= 0) {
@@ -17760,13 +17911,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
17760
17911
 
17761
17912
  \u2026(truncated)` : raw;
17762
17913
  }
17763
- var import_node_fs45, import_node_os14, import_node_path42, BUNDLED_SKILL_PREFIX;
17914
+ var import_node_fs46, import_node_os14, import_node_path43, BUNDLED_SKILL_PREFIX;
17764
17915
  var init_discover = __esm({
17765
17916
  "src/skills/discover.ts"() {
17766
17917
  "use strict";
17767
- import_node_fs45 = require("fs");
17918
+ import_node_fs46 = require("fs");
17768
17919
  import_node_os14 = require("os");
17769
- import_node_path42 = require("path");
17920
+ import_node_path43 = require("path");
17770
17921
  init_long_running();
17771
17922
  BUNDLED_SKILL_PREFIX = "bundled:";
17772
17923
  }
@@ -17860,8 +18011,8 @@ var init_expand = __esm({
17860
18011
  // src/skills/detached-job-path.ts
17861
18012
  function detachedJobScriptIn(dir) {
17862
18013
  for (const name of DETACHED_JOB_FILENAMES) {
17863
- const script = (0, import_node_path43.join)(dir, "scripts", name);
17864
- if ((0, import_node_fs46.existsSync)(script)) return script;
18014
+ const script = (0, import_node_path44.join)(dir, "scripts", name);
18015
+ if ((0, import_node_fs47.existsSync)(script)) return script;
17865
18016
  }
17866
18017
  return null;
17867
18018
  }
@@ -17873,11 +18024,11 @@ function packagedDetachedJobPath() {
17873
18024
  function resolveDetachedJobScript() {
17874
18025
  const packaged = packagedDetachedJobPath();
17875
18026
  if (packaged) return packaged;
17876
- let dir = (0, import_node_path43.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
18027
+ let dir = (0, import_node_path44.dirname)((0, import_node_url3.fileURLToPath)(import_meta3.url));
17877
18028
  for (let i = 0; i < 8; i++) {
17878
18029
  const candidate = detachedJobScriptIn(dir);
17879
18030
  if (candidate) return candidate;
17880
- const parent = (0, import_node_path43.dirname)(dir);
18031
+ const parent = (0, import_node_path44.dirname)(dir);
17881
18032
  if (parent === dir) break;
17882
18033
  dir = parent;
17883
18034
  }
@@ -17888,12 +18039,12 @@ function formatDetachedJobInvoke(scriptPath) {
17888
18039
  if (resolved) return `node ${JSON.stringify(resolved)}`;
17889
18040
  return "node scripts/detached-job.cjs";
17890
18041
  }
17891
- var import_node_fs46, import_node_path43, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
18042
+ var import_node_fs47, import_node_path44, import_node_url3, import_meta3, DETACHED_JOB_FILENAMES;
17892
18043
  var init_detached_job_path = __esm({
17893
18044
  "src/skills/detached-job-path.ts"() {
17894
18045
  "use strict";
17895
- import_node_fs46 = require("fs");
17896
- import_node_path43 = require("path");
18046
+ import_node_fs47 = require("fs");
18047
+ import_node_path44 = require("path");
17897
18048
  import_node_url3 = require("url");
17898
18049
  init_packaged_runtime();
17899
18050
  import_meta3 = {};
@@ -17971,7 +18122,7 @@ function formatWorktreeDirective(thread, opts) {
17971
18122
  );
17972
18123
  }
17973
18124
  lines.push(
17974
- '- Sideboard git buttons send short phrases ("Commit and push.", "Merge PR.", \u2026) with their meaning attached \u2014 act on them without asking for clarification. If the user gives a goal (Greptile 5/5, CI green, until checks pass), you get the watch-fix-push playbook with that request.'
18125
+ '- Sideboard git buttons send short phrases ("Commit and push.", "Ready for review.", "Merge PR.", \u2026) with their meaning attached \u2014 act on them without asking for clarification. If the user gives a goal (Greptile 5/5, CI green, until checks pass), you get the watch-fix-push playbook with that request.'
17975
18126
  );
17976
18127
  lines.push("");
17977
18128
  lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
@@ -18051,9 +18202,9 @@ function formatPrGateDirective() {
18051
18202
  }
18052
18203
  function formatProcessGuideDirective(opts) {
18053
18204
  const worktree = opts?.worktreePath?.trim();
18054
- const hasGraphSkill = !!worktree && (0, import_node_fs47.existsSync)((0, import_node_path44.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
18055
- const hasReviewSkill = !!worktree && (0, import_node_fs47.existsSync)((0, import_node_path44.join)(worktree, ".claude/skills/review/SKILL.md"));
18056
- const hasInstallSkill = !!worktree && (0, import_node_fs47.existsSync)((0, import_node_path44.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
18205
+ const hasGraphSkill = !!worktree && (0, import_node_fs48.existsSync)((0, import_node_path45.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
18206
+ const hasReviewSkill = !!worktree && (0, import_node_fs48.existsSync)((0, import_node_path45.join)(worktree, ".claude/skills/review/SKILL.md"));
18207
+ const hasInstallSkill = !!worktree && (0, import_node_fs48.existsSync)((0, import_node_path45.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
18057
18208
  return [
18058
18209
  "Process guides (recurring work only):",
18059
18210
  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,
@@ -18091,12 +18242,12 @@ function formatArtifactDirective() {
18091
18242
  function formatUiReminder() {
18092
18243
  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 or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
18093
18244
  }
18094
- var import_node_fs47, import_node_path44, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
18245
+ var import_node_fs48, import_node_path45, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
18095
18246
  var init_instructions = __esm({
18096
18247
  "src/agents/instructions.ts"() {
18097
18248
  "use strict";
18098
- import_node_fs47 = require("fs");
18099
- import_node_path44 = require("path");
18249
+ import_node_fs48 = require("fs");
18250
+ import_node_path45 = require("path");
18100
18251
  init_git_auth_mode();
18101
18252
  init_worktree_labels();
18102
18253
  init_detached_job_path();
@@ -18287,40 +18438,40 @@ __export(plan_file_exports, {
18287
18438
  writePlanFile: () => writePlanFile
18288
18439
  });
18289
18440
  function ensureAttachmentsGitignore(worktreePath) {
18290
- const gitignoreAbs = (0, import_node_path45.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
18291
- if ((0, import_node_fs48.existsSync)(gitignoreAbs)) return;
18292
- (0, import_node_fs48.mkdirSync)((0, import_node_path45.dirname)(gitignoreAbs), { recursive: true });
18293
- (0, import_node_fs48.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
18441
+ const gitignoreAbs = (0, import_node_path46.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
18442
+ if ((0, import_node_fs49.existsSync)(gitignoreAbs)) return;
18443
+ (0, import_node_fs49.mkdirSync)((0, import_node_path46.dirname)(gitignoreAbs), { recursive: true });
18444
+ (0, import_node_fs49.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
18294
18445
  }
18295
18446
  function planFileAbs(worktreePath) {
18296
- return (0, import_node_path45.join)(worktreePath, PLAN_FILE_REL);
18447
+ return (0, import_node_path46.join)(worktreePath, PLAN_FILE_REL);
18297
18448
  }
18298
18449
  function readTextIfPresent2(abs) {
18299
- if (!(0, import_node_fs48.existsSync)(abs)) return null;
18450
+ if (!(0, import_node_fs49.existsSync)(abs)) return null;
18300
18451
  try {
18301
- const content = (0, import_node_fs48.readFileSync)(abs, "utf8");
18452
+ const content = (0, import_node_fs49.readFileSync)(abs, "utf8");
18302
18453
  return content.trim() ? content : null;
18303
18454
  } catch {
18304
18455
  return null;
18305
18456
  }
18306
18457
  }
18307
18458
  function readPlanFile(worktreePath) {
18308
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path45.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path45.join)(worktreePath, LEGACY_PLAN_FILE_REL));
18459
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path46.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path46.join)(worktreePath, LEGACY_PLAN_FILE_REL));
18309
18460
  }
18310
18461
  function writePlanFile(worktreePath, content) {
18311
18462
  ensureAttachmentsGitignore(worktreePath);
18312
18463
  const abs = planFileAbs(worktreePath);
18313
- (0, import_node_fs48.mkdirSync)((0, import_node_path45.dirname)(abs), { recursive: true });
18464
+ (0, import_node_fs49.mkdirSync)((0, import_node_path46.dirname)(abs), { recursive: true });
18314
18465
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
18315
- (0, import_node_fs48.writeFileSync)(abs, body, "utf8");
18466
+ (0, import_node_fs49.writeFileSync)(abs, body, "utf8");
18316
18467
  return PLAN_FILE_REL;
18317
18468
  }
18318
- var import_node_fs48, import_node_path45;
18469
+ var import_node_fs49, import_node_path46;
18319
18470
  var init_plan_file = __esm({
18320
18471
  "src/plan/plan-file.ts"() {
18321
18472
  "use strict";
18322
- import_node_fs48 = require("fs");
18323
- import_node_path45 = require("path");
18473
+ import_node_fs49 = require("fs");
18474
+ import_node_path46 = require("path");
18324
18475
  init_workspace_scratch();
18325
18476
  init_plan_present();
18326
18477
  init_plan_present();
@@ -18380,7 +18531,7 @@ function setCaffeinateHoldHooks(next) {
18380
18531
  hooks = next;
18381
18532
  }
18382
18533
  function caffeinateHoldPath() {
18383
- return (0, import_node_path46.join)(appDataDir(), "caffeinate-hold.json");
18534
+ return (0, import_node_path47.join)(appDataDir(), "caffeinate-hold.json");
18384
18535
  }
18385
18536
  function processAlive(pid) {
18386
18537
  if (hooks.processAlive) return hooks.processAlive(pid);
@@ -18414,9 +18565,9 @@ function uniqueIds(ids) {
18414
18565
  }
18415
18566
  function readHold() {
18416
18567
  const path = caffeinateHoldPath();
18417
- if (!(0, import_node_fs49.existsSync)(path)) return null;
18568
+ if (!(0, import_node_fs50.existsSync)(path)) return null;
18418
18569
  try {
18419
- const parsed = JSON.parse((0, import_node_fs49.readFileSync)(path, "utf8"));
18570
+ const parsed = JSON.parse((0, import_node_fs50.readFileSync)(path, "utf8"));
18420
18571
  if (typeof parsed?.pid === "number" && parsed.pid > 0) {
18421
18572
  return {
18422
18573
  pid: parsed.pid,
@@ -18438,7 +18589,7 @@ function writeHold(pid, threadIds) {
18438
18589
  }
18439
18590
  function clearHold() {
18440
18591
  try {
18441
- (0, import_node_fs49.unlinkSync)(caffeinateHoldPath());
18592
+ (0, import_node_fs50.unlinkSync)(caffeinateHoldPath());
18442
18593
  } catch {
18443
18594
  }
18444
18595
  }
@@ -18496,7 +18647,7 @@ function setCaffeinateHold(enabled, opts) {
18496
18647
  if (platform !== "darwin") {
18497
18648
  return idleState(platform);
18498
18649
  }
18499
- const spawnImpl = hooks.spawn ?? import_node_child_process4.spawn;
18650
+ const spawnImpl = hooks.spawn ?? import_node_child_process5.spawn;
18500
18651
  const child = spawnImpl("caffeinate", ["-dimsu"], {
18501
18652
  detached: true,
18502
18653
  stdio: "ignore"
@@ -18523,13 +18674,13 @@ function releaseCaffeinateHoldForThread(threadId) {
18523
18674
  }
18524
18675
  return setCaffeinateHold(false, { threadId: id });
18525
18676
  }
18526
- var import_node_child_process4, import_node_fs49, import_node_path46, hooks;
18677
+ var import_node_child_process5, import_node_fs50, import_node_path47, hooks;
18527
18678
  var init_caffeinate_hold = __esm({
18528
18679
  "src/store/caffeinate-hold.ts"() {
18529
18680
  "use strict";
18530
- import_node_child_process4 = require("child_process");
18531
- import_node_fs49 = require("fs");
18532
- import_node_path46 = require("path");
18681
+ import_node_child_process5 = require("child_process");
18682
+ import_node_fs50 = require("fs");
18683
+ import_node_path47 = require("path");
18533
18684
  init_paths();
18534
18685
  init_private_file();
18535
18686
  hooks = {};
@@ -18538,7 +18689,7 @@ var init_caffeinate_hold = __esm({
18538
18689
 
18539
18690
  // src/store/schedules.ts
18540
18691
  function schedulesPath() {
18541
- return (0, import_node_path47.join)(appDataDir(), "schedules.json");
18692
+ return (0, import_node_path48.join)(appDataDir(), "schedules.json");
18542
18693
  }
18543
18694
  function parseDurationMs(every) {
18544
18695
  const m = every.trim().match(DURATION_RE);
@@ -18638,9 +18789,9 @@ function normalizeTask(raw) {
18638
18789
  }
18639
18790
  function readAll2() {
18640
18791
  const path = schedulesPath();
18641
- if (!(0, import_node_fs50.existsSync)(path)) return [];
18792
+ if (!(0, import_node_fs51.existsSync)(path)) return [];
18642
18793
  try {
18643
- const parsed = JSON.parse((0, import_node_fs50.readFileSync)(path, "utf8"));
18794
+ const parsed = JSON.parse((0, import_node_fs51.readFileSync)(path, "utf8"));
18644
18795
  if (!Array.isArray(parsed)) return [];
18645
18796
  return parsed.map((row) => {
18646
18797
  try {
@@ -18752,13 +18903,13 @@ function recordScheduleRun(id, result) {
18752
18903
  writeAll2(rows);
18753
18904
  return next;
18754
18905
  }
18755
- var import_node_crypto9, import_node_fs50, import_node_path47, import_croner, DURATION_RE, UNIT_MS;
18906
+ var import_node_crypto9, import_node_fs51, import_node_path48, import_croner, DURATION_RE, UNIT_MS;
18756
18907
  var init_schedules = __esm({
18757
18908
  "src/store/schedules.ts"() {
18758
18909
  "use strict";
18759
18910
  import_node_crypto9 = require("crypto");
18760
- import_node_fs50 = require("fs");
18761
- import_node_path47 = require("path");
18911
+ import_node_fs51 = require("fs");
18912
+ import_node_path48 = require("path");
18762
18913
  import_croner = require("croner");
18763
18914
  init_orchestrator_capable();
18764
18915
  init_paths();
@@ -18900,13 +19051,13 @@ var init_schedule_runner = __esm({
18900
19051
 
18901
19052
  // src/agents/cursor-store.ts
18902
19053
  function cursorSdkStoreDir(threadId) {
18903
- const root = (0, import_node_path48.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
19054
+ const root = (0, import_node_path49.join)(appDataDir(), CURSOR_SDK_STORE_DIR);
18904
19055
  const id = sanitizeCursorStoreSegment(threadId);
18905
19056
  if (!id) return root;
18906
- return (0, import_node_path48.join)(root, "threads", id);
19057
+ return (0, import_node_path49.join)(root, "threads", id);
18907
19058
  }
18908
19059
  function cursorSdkRunsNdjsonPath(threadId) {
18909
- return (0, import_node_path48.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
19060
+ return (0, import_node_path49.join)(cursorSdkStoreDir(threadId), "runs.ndjson");
18910
19061
  }
18911
19062
  function cursorSdkRunsNdjsonSearchPaths(threadId) {
18912
19063
  const scoped = cursorSdkRunsNdjsonPath(threadId);
@@ -18919,11 +19070,11 @@ function cursorSdkRunsNdjsonSearchPaths(threadId) {
18919
19070
  function sanitizeCursorStoreSegment(threadId) {
18920
19071
  return (threadId ?? "").trim().replace(/[^a-zA-Z0-9._-]/g, "_");
18921
19072
  }
18922
- var import_node_path48, CURSOR_SDK_STORE_DIR;
19073
+ var import_node_path49, CURSOR_SDK_STORE_DIR;
18923
19074
  var init_cursor_store = __esm({
18924
19075
  "src/agents/cursor-store.ts"() {
18925
19076
  "use strict";
18926
- import_node_path48 = require("path");
19077
+ import_node_path49 = require("path");
18927
19078
  init_paths();
18928
19079
  CURSOR_SDK_STORE_DIR = "cursor-sdk-store";
18929
19080
  }
@@ -18945,9 +19096,9 @@ function recoverFinishedCursorRun(opts) {
18945
19096
  return best;
18946
19097
  }
18947
19098
  function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
18948
- if (!(0, import_node_fs51.existsSync)(runsPath)) return null;
19099
+ if (!(0, import_node_fs52.existsSync)(runsPath)) return null;
18949
19100
  try {
18950
- const lines = (0, import_node_fs51.readFileSync)(runsPath, "utf8").split("\n");
19101
+ const lines = (0, import_node_fs52.readFileSync)(runsPath, "utf8").split("\n");
18951
19102
  let best = null;
18952
19103
  for (const line of lines) {
18953
19104
  const trimmed = line.trim();
@@ -18973,11 +19124,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
18973
19124
  return null;
18974
19125
  }
18975
19126
  }
18976
- var import_node_fs51;
19127
+ var import_node_fs52;
18977
19128
  var init_cursor_recover = __esm({
18978
19129
  "src/agents/cursor-recover.ts"() {
18979
19130
  "use strict";
18980
- import_node_fs51 = require("fs");
19131
+ import_node_fs52 = require("fs");
18981
19132
  init_cursor_store();
18982
19133
  }
18983
19134
  });
@@ -19109,13 +19260,13 @@ async function startOrchestration(opts) {
19109
19260
  }
19110
19261
  return updated;
19111
19262
  }
19112
- var import_node_events, import_node_fs52, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
19263
+ var import_node_events, import_node_fs53, LIVE_TURN_SPAWN_GRACE_MS, STALE_AGENT_PID_WAIT_MS, Orchestrator, singleton;
19113
19264
  var init_orchestrator = __esm({
19114
19265
  "src/orchestrator/orchestrator.ts"() {
19115
19266
  "use strict";
19116
19267
  import_node_events = require("events");
19117
19268
  init_outbound_watch();
19118
- import_node_fs52 = require("fs");
19269
+ import_node_fs53 = require("fs");
19119
19270
  init_error_detail();
19120
19271
  init_run();
19121
19272
  init_stale_lock();
@@ -19288,7 +19439,7 @@ var init_orchestrator = __esm({
19288
19439
  }
19289
19440
  continue;
19290
19441
  }
19291
- if (!(0, import_node_fs52.existsSync)(thread.worktreePath)) {
19442
+ if (!(0, import_node_fs53.existsSync)(thread.worktreePath)) {
19292
19443
  setStatus(thread.id, "broken", "Worktree missing on disk");
19293
19444
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
19294
19445
  continue;
@@ -20963,7 +21114,7 @@ var init_orchestrator = __esm({
20963
21114
  "ask_git targets a worktree agent thread (not the orchestrator). Pass a child/worktree thread ref."
20964
21115
  );
20965
21116
  }
20966
- if (action === "merge" && !thread.prUrl) {
21117
+ if ((action === "merge" || action === "ready-for-review") && !thread.prUrl) {
20967
21118
  throw new Error(
20968
21119
  "No pull request linked. Ask the worktree agent to open a draft PR first (ask_git create-draft)."
20969
21120
  );
@@ -21179,7 +21330,7 @@ var init_orchestrator = __esm({
21179
21330
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
21180
21331
  return restored2;
21181
21332
  }
21182
- if (!(0, import_node_fs52.existsSync)(thread.worktreePath)) {
21333
+ if (!(0, import_node_fs53.existsSync)(thread.worktreePath)) {
21183
21334
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
21184
21335
  throw new Error(
21185
21336
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
@@ -21256,13 +21407,14 @@ var init_orchestrator = __esm({
21256
21407
 
21257
21408
  // src/mcp/run-stdio.ts
21258
21409
  init_nested_electron_env();
21410
+ init_system_ca();
21259
21411
 
21260
21412
  // src/mcp/server.ts
21261
21413
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
21262
21414
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
21263
21415
  var import_zod8 = require("zod");
21264
21416
  var import_node_crypto12 = require("crypto");
21265
- var import_node_path51 = require("path");
21417
+ var import_node_path52 = require("path");
21266
21418
  init_orchestrator();
21267
21419
  init_worktree();
21268
21420
 
@@ -23854,27 +24006,27 @@ init_gh_errors();
23854
24006
  init_git_auth_mode();
23855
24007
 
23856
24008
  // src/board/load-home-board.ts
23857
- var import_node_fs54 = require("fs");
23858
- var import_node_path50 = require("path");
24009
+ var import_node_fs55 = require("fs");
24010
+ var import_node_path51 = require("path");
23859
24011
  init_worktree();
23860
24012
  init_paths();
23861
24013
 
23862
24014
  // src/board/board-pins.ts
23863
24015
  var import_node_crypto11 = require("crypto");
23864
- var import_node_fs53 = require("fs");
23865
- var import_node_path49 = require("path");
24016
+ var import_node_fs54 = require("fs");
24017
+ var import_node_path50 = require("path");
23866
24018
  init_paths();
23867
24019
  init_home_board();
23868
24020
  var FILE = "home-board-pins.json";
23869
24021
  var VERSION = 1;
23870
24022
  function pinsFile() {
23871
- return (0, import_node_path49.join)(appDataDir(), FILE);
24023
+ return (0, import_node_path50.join)(appDataDir(), FILE);
23872
24024
  }
23873
24025
  function readDisk() {
23874
24026
  const path = pinsFile();
23875
- if (!(0, import_node_fs53.existsSync)(path)) return [];
24027
+ if (!(0, import_node_fs54.existsSync)(path)) return [];
23876
24028
  try {
23877
- const raw = JSON.parse((0, import_node_fs53.readFileSync)(path, "utf8"));
24029
+ const raw = JSON.parse((0, import_node_fs54.readFileSync)(path, "utf8"));
23878
24030
  if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
23879
24031
  return raw.items.filter((item) => item?.id && item.kind && item.ref);
23880
24032
  } catch {
@@ -23882,8 +24034,8 @@ function readDisk() {
23882
24034
  }
23883
24035
  }
23884
24036
  function writeDisk(items) {
23885
- (0, import_node_fs53.mkdirSync)(appDataDir(), { recursive: true });
23886
- (0, import_node_fs53.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
24037
+ (0, import_node_fs54.mkdirSync)(appDataDir(), { recursive: true });
24038
+ (0, import_node_fs54.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
23887
24039
  }
23888
24040
  function listBoardPins() {
23889
24041
  return readDisk();
@@ -23904,7 +24056,7 @@ function homeBoardWorkspaceKey(workspaces) {
23904
24056
  return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
23905
24057
  }
23906
24058
  function cacheFile() {
23907
- return (0, import_node_path50.join)(appDataDir(), "home-board-cache.json");
24059
+ return (0, import_node_path51.join)(appDataDir(), "home-board-cache.json");
23908
24060
  }
23909
24061
  function emptyInputs() {
23910
24062
  return {
@@ -23930,9 +24082,9 @@ function shouldCacheHomeBoardInputs(inputs) {
23930
24082
  }
23931
24083
  function readDiskCache() {
23932
24084
  const path = cacheFile();
23933
- if (!(0, import_node_fs54.existsSync)(path)) return null;
24085
+ if (!(0, import_node_fs55.existsSync)(path)) return null;
23934
24086
  try {
23935
- const raw = JSON.parse((0, import_node_fs54.readFileSync)(path, "utf8"));
24087
+ const raw = JSON.parse((0, import_node_fs55.readFileSync)(path, "utf8"));
23936
24088
  if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
23937
24089
  return null;
23938
24090
  }
@@ -23946,8 +24098,8 @@ function readDiskCache() {
23946
24098
  }
23947
24099
  function writeDiskCache(entry) {
23948
24100
  try {
23949
- (0, import_node_fs54.mkdirSync)(appDataDir(), { recursive: true });
23950
- (0, import_node_fs54.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
24101
+ (0, import_node_fs55.mkdirSync)(appDataDir(), { recursive: true });
24102
+ (0, import_node_fs55.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
23951
24103
  } catch {
23952
24104
  }
23953
24105
  }
@@ -24075,6 +24227,54 @@ async function getHomeBoardInputs(workspaces, opts) {
24075
24227
 
24076
24228
  // src/mcp/server.ts
24077
24229
  init_home_board();
24230
+
24231
+ // src/mcp/create-thread-agent.ts
24232
+ init_cursor();
24233
+ function resolveOrchCreateThreadOptions(input) {
24234
+ const { resolveNewThreadOptions: resolveNewThreadOptions2 } = input;
24235
+ const account = resolveNewThreadOptions2({});
24236
+ const requested = input.requestedAgent;
24237
+ const parent = input.parentAgent ?? void 0;
24238
+ const cursorReady = input.cursorReady ?? isCursorApiKeyConfigured();
24239
+ let agent = account.agent;
24240
+ let ignoredAgent;
24241
+ let honorRequestedModel = false;
24242
+ if (requested) {
24243
+ const parentEcho = Boolean(parent) && requested === parent && requested !== account.agent;
24244
+ const cursorAutofill = requested === "cursor" && account.agent !== "cursor";
24245
+ if (parentEcho || cursorAutofill) {
24246
+ ignoredAgent = requested;
24247
+ } else {
24248
+ agent = requested;
24249
+ honorRequestedModel = input.requestedModel !== void 0;
24250
+ }
24251
+ }
24252
+ let coercedFrom;
24253
+ if (agent === "codex" && parent === "codex" && cursorReady) {
24254
+ coercedFrom = requested ?? "codex";
24255
+ agent = "cursor";
24256
+ }
24257
+ const opts = resolveNewThreadOptions2({
24258
+ agent,
24259
+ model: honorRequestedModel ? input.requestedModel : void 0
24260
+ });
24261
+ return {
24262
+ ...opts,
24263
+ ...ignoredAgent ? { ignoredAgent } : {},
24264
+ ...coercedFrom ? { coercedFrom } : {}
24265
+ };
24266
+ }
24267
+ function orchCreateThreadAgentNote(input) {
24268
+ if (input.coercedFrom) {
24269
+ return `Avoid nested Codex under a Codex orchestrator \u2014 used agent=${input.agent}`;
24270
+ }
24271
+ if (input.ignoredAgent) {
24272
+ return `Ignored agent=${input.ignoredAgent} \u2014 used Account default agent=${input.agent}`;
24273
+ }
24274
+ return void 0;
24275
+ }
24276
+
24277
+ // src/mcp/server.ts
24078
24278
  var MAX_ORCH_THREADS = 5;
24079
24279
  var CREATE_THREAD_TIMEOUT_MS = 9e4;
24080
24280
  function withTimeout(promise, ms, label) {
@@ -24122,18 +24322,13 @@ async function createOrchChildThread(orch, args, resolveNewThreadOptions2) {
24122
24322
  };
24123
24323
  }
24124
24324
  }
24125
- let agentArg = args.agent;
24126
- let agentCoercedFrom;
24127
- const resolvedProbe = resolveNewThreadOptions2({ agent: agentArg }).agent;
24128
- if (resolvedProbe === "codex") {
24129
- agentCoercedFrom = agentArg ?? "codex";
24130
- const accountAgent = resolveNewThreadOptions2({}).agent;
24131
- agentArg = accountAgent !== "codex" ? accountAgent : "cursor";
24132
- }
24133
- const opts = resolveNewThreadOptions2({
24134
- agent: agentArg,
24135
- model: args.model
24325
+ const opts = resolveOrchCreateThreadOptions({
24326
+ requestedAgent: args.agent,
24327
+ requestedModel: args.model,
24328
+ parentAgent: parent?.agent,
24329
+ resolveNewThreadOptions: resolveNewThreadOptions2
24136
24330
  });
24331
+ const agentNote = orchCreateThreadAgentNote(opts);
24137
24332
  try {
24138
24333
  const priorIds = new Set(orch.getThreads(false).map((t) => t.id));
24139
24334
  const thread = await withTimeout(
@@ -24169,10 +24364,9 @@ async function createOrchChildThread(orch, args, resolveNewThreadOptions2) {
24169
24364
  link: `sideboard://thread/${thread.id}`,
24170
24365
  parentThreadId: thread.parentThreadId,
24171
24366
  ...alreadyStarted ? { alreadyStarted: true } : {},
24172
- ...agentCoercedFrom ? {
24173
- agentCoercedFrom,
24174
- note: `Avoid nested Codex under a Codex orchestrator \u2014 used Account default agent=${thread.agent}`
24175
- } : {},
24367
+ ...opts.coercedFrom ? { agentCoercedFrom: opts.coercedFrom } : {},
24368
+ ...opts.ignoredAgent ? { agentIgnored: opts.ignoredAgent } : {},
24369
+ ...agentNote ? { note: agentNote } : {},
24176
24370
  ...parentCorrectedFrom ? { parentCorrectedFrom, parentNote } : {}
24177
24371
  })
24178
24372
  };
@@ -24247,7 +24441,7 @@ async function startMcpServer() {
24247
24441
  async () => {
24248
24442
  const threads = orch.getThreads(true);
24249
24443
  const lines = threads.map((t) => {
24250
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path51.basename)(t.repoPath) || t.repoPath;
24444
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path52.basename)(t.repoPath) || t.repoPath;
24251
24445
  const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
24252
24446
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
24253
24447
  const preview = lastMessagePreview(t.messages, 80);
@@ -24532,11 +24726,13 @@ async function startMcpServer() {
24532
24726
  );
24533
24727
  server.tool(
24534
24728
  "create_thread",
24535
- `Create a worktree thread (chat) from branch, pr, or ticket. A ticket, PR, or named branch may have only one live worktree \u2014 if one already matches, returns it (alreadyStarted=true) instead of a second checkout. Creating from the default branch still opens a new isolated worktree. Pass repoPath from list_workspaces. cowboy=true uses the project folder on the default branch (no isolated worktree; land is commit+push). From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn (skipped for cowboy). Then use send_to_thread to chat.`,
24729
+ `Create a worktree thread (chat) from branch, pr, or ticket. A ticket, PR, or named branch may have only one live worktree \u2014 if one already matches, returns it (alreadyStarted=true) instead of a second checkout. Creating from the default branch still opens a new isolated worktree. Pass repoPath from list_workspaces. cowboy=true uses the project folder on the default branch (no isolated worktree; land is commit+push). From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Omit agent/model \u2014 Sideboard applies ${accountDefaultsHint}. Do not pass your own agent or agent=cursor; those are ignored. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn (skipped for cowboy). Then use send_to_thread to chat.`,
24536
24730
  {
24537
24731
  sourceType: import_zod8.z.enum(["branch", "pr", "ticket"]),
24538
24732
  sourceRef: import_zod8.z.string(),
24539
- agent: import_zod8.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]).optional().describe(`Omit to use Account default agent (${accountDefaults.agent})`),
24733
+ agent: import_zod8.z.enum(["claude", "codex", "opencode", "brightsy", "cursor"]).optional().describe(
24734
+ `Usually omit. Sideboard uses Account default agent (${accountDefaults.agent}). Passing your own agent or cursor is ignored.`
24735
+ ),
24540
24736
  model: import_zod8.z.string().nullable().optional().describe(
24541
24737
  `Usually omit to use Account default model (${accountDefaults.model?.trim() || "Auto"}). Pass null only to force Auto / agent-default.`
24542
24738
  ),
@@ -24840,11 +25036,11 @@ async function startMcpServer() {
24840
25036
  );
24841
25037
  server.tool(
24842
25038
  "ask_git",
24843
- "Commit & push, open a draft PR, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=merge only when the user explicitly asked to merge that PR. Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
25039
+ "Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=ready-for-review and action=merge only when the user explicitly asked (or clicked the desktop button). Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
24844
25040
  {
24845
25041
  ref: import_zod8.z.string().describe("Worktree thread id/ref"),
24846
25042
  action: import_zod8.z.enum(AGENT_GIT_ACTIONS).describe(
24847
- "commit-push | create-draft | create-web | resolve-conflicts | merge"
25043
+ "commit-push | create-draft | create-web | resolve-conflicts | ready-for-review | merge"
24848
25044
  )
24849
25045
  },
24850
25046
  async ({ ref, action }) => {
@@ -25243,6 +25439,12 @@ async function startMcpServer() {
25243
25439
 
25244
25440
  // src/mcp/run-stdio.ts
25245
25441
  dropNestedElectronEnvFromProcess();
25442
+ var systemCaBundle = materializeSystemCaBundle();
25443
+ if (systemCaBundle && !process.env.NODE_EXTRA_CA_CERTS?.trim()) {
25444
+ process.env.NODE_EXTRA_CA_CERTS = systemCaBundle;
25445
+ }
25446
+ applySystemCaEnv(process.env);
25447
+ trustSystemCertificates();
25246
25448
  startMcpServer().catch((err) => {
25247
25449
  console.error(err);
25248
25450
  process.exitCode = 1;