@sideboard-ai/core 0.1.238 → 0.1.240

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.
@@ -10212,12 +10212,14 @@ function skillCommandFromInput(input) {
10212
10212
  }
10213
10213
  return void 0;
10214
10214
  }
10215
+ function looksLikeComposerSkillExpansion(text7) {
10216
+ const t = text7.trim();
10217
+ return /^## Skill: \//m.test(t) && /Follow this skill for the request above:/i.test(t);
10218
+ }
10215
10219
  function looksLikeSkillBody(text7) {
10216
10220
  const t = text7.trim();
10217
10221
  if (!t) return false;
10218
- if (/^## Skill: \//m.test(t) && /Follow this skill for the request above:/i.test(t)) {
10219
- return true;
10220
- }
10222
+ if (looksLikeComposerSkillExpansion(t)) return true;
10221
10223
  return skillNameFromFrontmatter(t) != null;
10222
10224
  }
10223
10225
  function skillNameFromFrontmatter(text7) {
@@ -10238,11 +10240,13 @@ function isCompactToolName(name) {
10238
10240
  short
10239
10241
  );
10240
10242
  }
10241
- function isContextCompactInProgress(text7) {
10242
- return /^Compressing context/i.test(text7.trim());
10243
- }
10244
10243
  function isContextCompactDone(text7) {
10245
- return /^Context compressed\b/i.test(text7.trim());
10244
+ return /\bContext compressed\b/i.test(text7.trim());
10245
+ }
10246
+ function isContextCompactInProgress(text7) {
10247
+ const t = text7.trim();
10248
+ if (isContextCompactDone(t)) return false;
10249
+ return /^Compressing context/i.test(t);
10246
10250
  }
10247
10251
  function looksLikeConversationSummary(text7) {
10248
10252
  const t = text7.trim();
@@ -10666,7 +10670,7 @@ function applyAgentEvent(parts, event) {
10666
10670
  );
10667
10671
  }
10668
10672
  const acc = next[next.length - 1];
10669
- if (acc?.type === "text" && looksLikeSkillBody(acc.text)) {
10673
+ if (acc?.type === "text" && looksLikeComposerSkillExpansion(acc.text)) {
10670
10674
  next[next.length - 1] = skillToolFromTextPart(acc, `skill-${next.length}`);
10671
10675
  } else if (acc?.type === "text" && looksLikeConversationSummary(acc.text)) {
10672
10676
  next[next.length - 1] = compactToolPart(acc.text, `compact-${next.length}`, {
@@ -11236,10 +11240,10 @@ function eventsFromClaudeSystem(obj) {
11236
11240
  if (subtype === "api_retry") {
11237
11241
  const attempt = obj.attempt;
11238
11242
  const max = obj.max_retries;
11239
- const delay = obj.retry_delay_ms;
11243
+ const delay2 = obj.retry_delay_ms;
11240
11244
  return {
11241
11245
  type: "thinking",
11242
- data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay === "number" ? ` (wait ${delay}ms)` : ""}`
11246
+ data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay2 === "number" ? ` (wait ${delay2}ms)` : ""}`
11243
11247
  };
11244
11248
  }
11245
11249
  if (subtype === "status") {
@@ -11254,7 +11258,8 @@ function eventsFromClaudeSystem(obj) {
11254
11258
  const trigger = meta.trigger ? ` (${meta.trigger})` : "";
11255
11259
  const thinking = {
11256
11260
  type: "thinking",
11257
- data: `Context compressed${trigger}`
11261
+ data: `Context compressed${trigger}`,
11262
+ replace: true
11258
11263
  };
11259
11264
  if (meta.postTokens != null && meta.postTokens > 0) {
11260
11265
  return [
@@ -14525,15 +14530,76 @@ var init_request_review = __esm({
14525
14530
  }
14526
14531
  });
14527
14532
 
14533
+ // src/hook/worktree-run-ports.ts
14534
+ function worktreeRunPortsPath(worktreePath) {
14535
+ return (0, import_node_path38.join)(worktreePath, RUN_PORTS_REL);
14536
+ }
14537
+ function isPort(value) {
14538
+ return typeof value === "number" && Number.isInteger(value) && value > 0 && value <= 65535;
14539
+ }
14540
+ function parseFile(raw) {
14541
+ try {
14542
+ const parsed = JSON.parse(raw);
14543
+ if (!parsed || typeof parsed !== "object") return {};
14544
+ const scripts = parsed.scripts;
14545
+ if (!scripts || typeof scripts !== "object") return {};
14546
+ const next = {};
14547
+ for (const [name, ports] of Object.entries(scripts)) {
14548
+ if (!name || !Array.isArray(ports)) continue;
14549
+ const cleaned = ports.filter(isPort);
14550
+ if (cleaned.length) next[name] = cleaned;
14551
+ }
14552
+ return { scripts: next };
14553
+ } catch {
14554
+ return {};
14555
+ }
14556
+ }
14557
+ function loadWorktreeRunPorts(worktreePath, scriptName) {
14558
+ if (!worktreePath.trim() || !scriptName.trim()) return null;
14559
+ try {
14560
+ const raw = (0, import_node_fs38.readFileSync)(worktreeRunPortsPath(worktreePath), "utf8");
14561
+ const ports = parseFile(raw).scripts?.[scriptName];
14562
+ return ports?.length ? ports : null;
14563
+ } catch {
14564
+ return null;
14565
+ }
14566
+ }
14567
+ function saveWorktreeRunPorts(worktreePath, scriptName, ports) {
14568
+ if (!worktreePath.trim() || !scriptName.trim()) return;
14569
+ const cleaned = ports.filter(isPort);
14570
+ if (!cleaned.length) return;
14571
+ const path = worktreeRunPortsPath(worktreePath);
14572
+ let current = {};
14573
+ try {
14574
+ current = parseFile((0, import_node_fs38.readFileSync)(path, "utf8"));
14575
+ } catch {
14576
+ current = {};
14577
+ }
14578
+ const scripts = { ...current.scripts ?? {} };
14579
+ scripts[scriptName] = cleaned;
14580
+ (0, import_node_fs38.mkdirSync)((0, import_node_path38.dirname)(path), { recursive: true });
14581
+ (0, import_node_fs38.writeFileSync)(path, `${JSON.stringify({ scripts }, null, 2)}
14582
+ `, "utf8");
14583
+ }
14584
+ var import_node_fs38, import_node_path38, RUN_PORTS_REL;
14585
+ var init_worktree_run_ports = __esm({
14586
+ "src/hook/worktree-run-ports.ts"() {
14587
+ "use strict";
14588
+ import_node_fs38 = require("fs");
14589
+ import_node_path38 = require("path");
14590
+ RUN_PORTS_REL = ".context/.sideboard/run-ports.json";
14591
+ }
14592
+ });
14593
+
14528
14594
  // src/hook/conductor.ts
14529
14595
  function matchSimpleGlob(pattern, name) {
14530
14596
  const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
14531
14597
  return new RegExp(`^${escaped}$`).test(name);
14532
14598
  }
14533
14599
  function readWorktreeInclude(repoPath) {
14534
- const path = (0, import_node_path38.join)(repoPath, ".worktreeinclude");
14535
- if (!(0, import_node_fs38.existsSync)(path)) return [];
14536
- return (0, import_node_fs38.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
14600
+ const path = (0, import_node_path39.join)(repoPath, ".worktreeinclude");
14601
+ if (!(0, import_node_fs39.existsSync)(path)) return [];
14602
+ return (0, import_node_fs39.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
14537
14603
  }
14538
14604
  function resolveFilesToCopy(repoPath) {
14539
14605
  const fromInclude = readWorktreeInclude(repoPath);
@@ -14543,10 +14609,10 @@ function resolveFilesToCopy(repoPath) {
14543
14609
  if (settings?.fileIncludeGlobs?.length) {
14544
14610
  const matched = [];
14545
14611
  try {
14546
- for (const entry of (0, import_node_fs38.readdirSync)(repoPath, { withFileTypes: true })) {
14612
+ for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
14547
14613
  if (!entry.isFile()) continue;
14548
14614
  for (const glob of settings.fileIncludeGlobs) {
14549
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path38.basename)(glob), entry.name)) {
14615
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path39.basename)(glob), entry.name)) {
14550
14616
  matched.push(entry.name);
14551
14617
  break;
14552
14618
  }
@@ -14558,7 +14624,7 @@ function resolveFilesToCopy(repoPath) {
14558
14624
  }
14559
14625
  const defaults = [];
14560
14626
  try {
14561
- for (const entry of (0, import_node_fs38.readdirSync)(repoPath, { withFileTypes: true })) {
14627
+ for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
14562
14628
  if (entry.isFile() && entry.name.startsWith(".env")) {
14563
14629
  defaults.push(entry.name);
14564
14630
  }
@@ -14572,11 +14638,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
14572
14638
  const patterns = resolveFilesToCopy(repoPath);
14573
14639
  const copied = [];
14574
14640
  for (const rel of patterns) {
14575
- const src = (0, import_node_path38.join)(repoPath, rel);
14576
- if (!(0, import_node_fs38.existsSync)(src)) continue;
14577
- const dest = (0, import_node_path38.join)(worktreePath, rel);
14578
- (0, import_node_fs38.mkdirSync)((0, import_node_path38.dirname)(dest), { recursive: true });
14579
- (0, import_node_fs38.copyFileSync)(src, dest);
14641
+ const src = (0, import_node_path39.join)(repoPath, rel);
14642
+ if (!(0, import_node_fs39.existsSync)(src)) continue;
14643
+ const dest = (0, import_node_path39.join)(worktreePath, rel);
14644
+ (0, import_node_fs39.mkdirSync)((0, import_node_path39.dirname)(dest), { recursive: true });
14645
+ (0, import_node_fs39.copyFileSync)(src, dest);
14580
14646
  copied.push(rel);
14581
14647
  }
14582
14648
  return copied;
@@ -14611,7 +14677,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
14611
14677
  const env = stripNestedElectronEnv({
14612
14678
  ...baseEnv ?? process.env
14613
14679
  });
14614
- const name = opts.workspaceName ?? (0, import_node_path38.basename)(opts.worktreePath);
14680
+ const name = opts.workspaceName ?? (0, import_node_path39.basename)(opts.worktreePath);
14615
14681
  const ports = opts.ports ?? [];
14616
14682
  const primary = ports[0];
14617
14683
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -14651,6 +14717,57 @@ function killableListenerPids(raw, selfPid = process.pid) {
14651
14717
  }
14652
14718
  return pids;
14653
14719
  }
14720
+ function listUnixListenerPids(port, selfPid) {
14721
+ try {
14722
+ const raw = (0, import_node_child_process4.execFileSync)("lsof", [`-tiTCP:${port}`, "-sTCP:LISTEN"], {
14723
+ encoding: "utf8",
14724
+ stdio: ["ignore", "pipe", "ignore"],
14725
+ timeout: 2e3
14726
+ });
14727
+ return killableListenerPids(raw, selfPid);
14728
+ } catch {
14729
+ return [];
14730
+ }
14731
+ }
14732
+ function listenerCwd(pid) {
14733
+ if (!Number.isFinite(pid) || pid <= 0) return null;
14734
+ try {
14735
+ const raw = (0, import_node_child_process4.execFileSync)("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], {
14736
+ encoding: "utf8",
14737
+ stdio: ["ignore", "pipe", "ignore"],
14738
+ timeout: 2e3
14739
+ });
14740
+ for (const line of raw.split("\n")) {
14741
+ if (line.startsWith("n") && line.length > 1) return line.slice(1);
14742
+ }
14743
+ } catch {
14744
+ }
14745
+ return null;
14746
+ }
14747
+ function realpathOrResolve(path) {
14748
+ try {
14749
+ return (0, import_node_fs39.realpathSync)(path);
14750
+ } catch {
14751
+ return (0, import_node_path39.resolve)(path);
14752
+ }
14753
+ }
14754
+ function isOtherWorktreeListenerCwd(cwd, worktreePath) {
14755
+ const wt = realpathOrResolve(worktreePath);
14756
+ const c = realpathOrResolve(cwd);
14757
+ if (c === wt || c.startsWith(wt + import_node_path39.sep)) return false;
14758
+ const parent = (0, import_node_path39.dirname)(wt);
14759
+ const thisName = (0, import_node_path39.basename)(wt);
14760
+ if (!thisName || c === parent) return false;
14761
+ if (!c.startsWith(parent + import_node_path39.sep)) return false;
14762
+ const first = c.slice(parent.length + 1).split(import_node_path39.sep)[0];
14763
+ return Boolean(first) && first !== thisName;
14764
+ }
14765
+ function signalPid(pid, signal) {
14766
+ try {
14767
+ process.kill(pid, signal);
14768
+ } catch {
14769
+ }
14770
+ }
14654
14771
  function killListenersOnPorts(ports) {
14655
14772
  const selfPid = process.pid;
14656
14773
  for (const port of ports) {
@@ -14668,26 +14785,32 @@ function killListenersOnPorts(ports) {
14668
14785
  );
14669
14786
  continue;
14670
14787
  }
14671
- let raw = "";
14672
- try {
14673
- raw = (0, import_node_child_process4.execFileSync)("lsof", [`-tiTCP:${port}`, "-sTCP:LISTEN"], {
14674
- encoding: "utf8",
14675
- stdio: ["ignore", "pipe", "ignore"],
14676
- timeout: 2e3
14677
- });
14678
- } catch {
14679
- continue;
14680
- }
14681
- for (const pid of killableListenerPids(raw, selfPid)) {
14682
- try {
14683
- process.kill(pid, "SIGTERM");
14684
- } catch {
14685
- }
14788
+ for (const pid of listUnixListenerPids(port, selfPid)) {
14789
+ signalPid(pid, "SIGTERM");
14686
14790
  }
14687
14791
  } catch {
14688
14792
  }
14689
14793
  }
14690
14794
  }
14795
+ function killStaleWorktreeListeners(ports, worktreePath, signal = "SIGTERM") {
14796
+ if (!worktreePath.trim()) {
14797
+ killListenersOnPorts(ports);
14798
+ return;
14799
+ }
14800
+ if (process.platform === "win32") {
14801
+ killListenersOnPorts(ports);
14802
+ return;
14803
+ }
14804
+ const selfPid = process.pid;
14805
+ for (const port of ports) {
14806
+ if (!Number.isFinite(port) || port <= 0) continue;
14807
+ for (const pid of listUnixListenerPids(port, selfPid)) {
14808
+ const cwd = listenerCwd(pid);
14809
+ if (cwd && isOtherWorktreeListenerCwd(cwd, worktreePath)) continue;
14810
+ signalPid(pid, signal);
14811
+ }
14812
+ }
14813
+ }
14691
14814
  function killScriptTree(child, ports = []) {
14692
14815
  const pid = child.pid;
14693
14816
  if (pid) {
@@ -14849,7 +14972,7 @@ function getRunMode(worktreePath, repoPath) {
14849
14972
  return loadWorkspaceSettings(worktreePath, repoPath)?.runMode ?? "concurrent";
14850
14973
  }
14851
14974
  async function reservePort() {
14852
- return new Promise((resolve, reject) => {
14975
+ return new Promise((resolve2, reject) => {
14853
14976
  const server = (0, import_node_net.createServer)();
14854
14977
  let released = false;
14855
14978
  const release = () => new Promise((res) => {
@@ -14866,13 +14989,14 @@ async function reservePort() {
14866
14989
  void release().then(() => reject(new Error("Failed to allocate port")));
14867
14990
  return;
14868
14991
  }
14869
- resolve({ port: addr.port, release });
14992
+ resolve2({ port: addr.port, release });
14870
14993
  });
14871
14994
  server.on("error", reject);
14872
14995
  });
14873
14996
  }
14874
14997
  async function tryReservePort(port) {
14875
- return new Promise((resolve) => {
14998
+ if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
14999
+ return new Promise((resolve2) => {
14876
15000
  const server = (0, import_node_net.createServer)();
14877
15001
  let released = false;
14878
15002
  const release = () => new Promise((res) => {
@@ -14883,23 +15007,51 @@ async function tryReservePort(port) {
14883
15007
  released = true;
14884
15008
  server.close(() => res());
14885
15009
  });
14886
- server.once("error", () => resolve(null));
15010
+ server.once("error", () => {
15011
+ try {
15012
+ server.close();
15013
+ } catch {
15014
+ }
15015
+ resolve2(null);
15016
+ });
14887
15017
  server.listen(port, "127.0.0.1", () => {
14888
- resolve({ port, release });
15018
+ resolve2({ port, release });
14889
15019
  });
14890
15020
  });
14891
15021
  }
14892
- async function reservePortRange(size = PORT_RANGE_SIZE) {
14893
- const held = [await reservePort()];
14894
- const base = held[0].port;
15022
+ function normalizePreferredPorts(ports, size) {
15023
+ if (!ports?.length) return [];
15024
+ const seen = /* @__PURE__ */ new Set();
15025
+ const out = [];
15026
+ for (const p of ports) {
15027
+ if (!Number.isInteger(p) || p <= 0 || p > 65535 || seen.has(p)) continue;
15028
+ seen.add(p);
15029
+ out.push(p);
15030
+ if (out.length >= size) break;
15031
+ }
15032
+ return out;
15033
+ }
15034
+ function delay(ms) {
15035
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
15036
+ }
15037
+ async function fillPortRange(held, size) {
15038
+ if (held.length >= size) return held;
15039
+ const base = held[0]?.port;
15040
+ const taken = new Set(held.map((h) => h.port));
14895
15041
  try {
14896
- for (let i = 1; i < size; i++) {
14897
- const candidate = base + i;
14898
- const next = await tryReservePort(candidate);
15042
+ let offset = 0;
15043
+ while (held.length < size) {
15044
+ const candidate = base != null ? base + offset : null;
15045
+ offset += 1;
15046
+ if (candidate != null && taken.has(candidate)) continue;
15047
+ const next = candidate != null ? await tryReservePort(candidate) : null;
14899
15048
  if (next) {
14900
15049
  held.push(next);
15050
+ taken.add(next.port);
14901
15051
  } else {
14902
- held.push(await reservePort());
15052
+ const ephemeral = await reservePort();
15053
+ held.push(ephemeral);
15054
+ taken.add(ephemeral.port);
14903
15055
  }
14904
15056
  }
14905
15057
  return held;
@@ -14908,11 +15060,59 @@ async function reservePortRange(size = PORT_RANGE_SIZE) {
14908
15060
  throw err;
14909
15061
  }
14910
15062
  }
15063
+ async function tryReserveAvailablePorts(ports) {
15064
+ const held = [];
15065
+ for (const port of ports) {
15066
+ const next = await tryReservePort(port);
15067
+ if (next) held.push(next);
15068
+ }
15069
+ return held;
15070
+ }
15071
+ async function reclaimPreferredPorts(ports, worktreePath) {
15072
+ const primary = ports[0];
15073
+ if (primary == null) return null;
15074
+ const takePrimary = async () => {
15075
+ const held2 = await tryReserveAvailablePorts(ports);
15076
+ if (held2.some((h) => h.port === primary)) return held2;
15077
+ await Promise.all(held2.map((h) => h.release()));
15078
+ return null;
15079
+ };
15080
+ let held = await takePrimary();
15081
+ if (held) return held;
15082
+ if (worktreePath) {
15083
+ killStaleWorktreeListeners(ports, worktreePath, "SIGTERM");
15084
+ } else {
15085
+ killListenersOnPorts(ports);
15086
+ }
15087
+ for (let i = 0; i < RECLAIM_TRIES; i++) {
15088
+ await delay(RECLAIM_RETRY_DELAY_MS);
15089
+ held = await takePrimary();
15090
+ if (held) return held;
15091
+ if (i === 2 && worktreePath) {
15092
+ killStaleWorktreeListeners(ports, worktreePath, "SIGKILL");
15093
+ }
15094
+ }
15095
+ return null;
15096
+ }
15097
+ async function reservePortRange(size = PORT_RANGE_SIZE, opts) {
15098
+ const preferred = normalizePreferredPorts(opts?.preferred, size);
15099
+ if (preferred.length) {
15100
+ const reused = await reclaimPreferredPorts(preferred, opts?.worktreePath);
15101
+ if (reused) return fillPortRange(reused, size);
15102
+ }
15103
+ const held = [await reservePort()];
15104
+ return fillPortRange(held, size);
15105
+ }
14911
15106
  async function startDevServer(repoPath, worktreePath, onLine, opts) {
14912
15107
  const script = getRunScript(worktreePath, repoPath, opts?.scriptName);
14913
15108
  if (!script) return null;
14914
- const held = await reservePortRange(PORT_RANGE_SIZE);
15109
+ const preferred = loadWorktreeRunPorts(worktreePath, script.name) ?? opts?.preferredPorts;
15110
+ const held = await reservePortRange(PORT_RANGE_SIZE, {
15111
+ preferred: preferred ?? void 0,
15112
+ worktreePath
15113
+ });
14915
15114
  const ports = held.map((h) => h.port);
15115
+ saveWorktreeRunPorts(worktreePath, script.name, ports);
14916
15116
  try {
14917
15117
  const handle = await spawnWorkspaceScript(script.command, {
14918
15118
  worktreePath,
@@ -14935,14 +15135,14 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
14935
15135
  throw err;
14936
15136
  }
14937
15137
  }
14938
- var import_node_fs38, import_node_child_process4, import_node_net, import_node_path38, import_execa4, import_node_readline3, PORT_RANGE_SIZE, cachedLoginEnv;
15138
+ var import_node_fs39, import_node_child_process4, import_node_net, import_node_path39, import_execa4, import_node_readline3, PORT_RANGE_SIZE, RECLAIM_RETRY_DELAY_MS, RECLAIM_TRIES, cachedLoginEnv;
14939
15139
  var init_conductor = __esm({
14940
15140
  "src/hook/conductor.ts"() {
14941
15141
  "use strict";
14942
- import_node_fs38 = require("fs");
15142
+ import_node_fs39 = require("fs");
14943
15143
  import_node_child_process4 = require("child_process");
14944
15144
  import_node_net = require("net");
14945
- import_node_path38 = require("path");
15145
+ import_node_path39 = require("path");
14946
15146
  import_execa4 = require("execa");
14947
15147
  import_node_readline3 = require("readline");
14948
15148
  init_settings();
@@ -14953,8 +15153,12 @@ var init_conductor = __esm({
14953
15153
  init_git_auth_mode();
14954
15154
  init_request_review();
14955
15155
  init_worktree_exclude();
15156
+ init_worktree_run_ports();
15157
+ init_worktree_run_ports();
14956
15158
  init_nested_electron_env();
14957
15159
  PORT_RANGE_SIZE = 10;
15160
+ RECLAIM_RETRY_DELAY_MS = 40;
15161
+ RECLAIM_TRIES = 8;
14958
15162
  cachedLoginEnv = null;
14959
15163
  }
14960
15164
  });
@@ -14992,7 +15196,7 @@ function materialize(mem) {
14992
15196
  };
14993
15197
  }
14994
15198
  function setupLogPath(threadId) {
14995
- return (0, import_node_path39.join)(threadsDir(), `${threadId}.setup.log.json`);
15199
+ return (0, import_node_path40.join)(threadsDir(), `${threadId}.setup.log.json`);
14996
15200
  }
14997
15201
  function setupLogKeyForWorktree(worktreePath) {
14998
15202
  const norm = normalizeWorktreePath(worktreePath);
@@ -15010,7 +15214,7 @@ function persistNow(threadId) {
15010
15214
  const mem = memory.get(threadId);
15011
15215
  if (!mem) return;
15012
15216
  try {
15013
- (0, import_node_fs39.writeFileSync)(
15217
+ (0, import_node_fs40.writeFileSync)(
15014
15218
  setupLogPath(threadId),
15015
15219
  `${JSON.stringify(materialize(mem))}
15016
15220
  `,
@@ -15031,9 +15235,9 @@ function schedulePersist(threadId) {
15031
15235
  }
15032
15236
  function loadFromDisk(threadId) {
15033
15237
  const path = setupLogPath(threadId);
15034
- if (!(0, import_node_fs39.existsSync)(path)) return null;
15238
+ if (!(0, import_node_fs40.existsSync)(path)) return null;
15035
15239
  try {
15036
- const raw = JSON.parse((0, import_node_fs39.readFileSync)(path, "utf8"));
15240
+ const raw = JSON.parse((0, import_node_fs40.readFileSync)(path, "utf8"));
15037
15241
  return {
15038
15242
  output: typeof raw.output === "string" ? raw.output : "",
15039
15243
  running: Boolean(raw.running),
@@ -15089,13 +15293,13 @@ function finishSetupLog(threadId, exitCode, source) {
15089
15293
  persistNow(threadId);
15090
15294
  return materialize(mem);
15091
15295
  }
15092
- var import_node_crypto8, import_node_fs39, import_node_path39, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers, PERSIST_DEBOUNCE_MS;
15296
+ var import_node_crypto8, import_node_fs40, import_node_path40, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers, PERSIST_DEBOUNCE_MS;
15093
15297
  var init_setup_log = __esm({
15094
15298
  "src/store/setup-log.ts"() {
15095
15299
  "use strict";
15096
15300
  import_node_crypto8 = require("crypto");
15097
- import_node_fs39 = require("fs");
15098
- import_node_path39 = require("path");
15301
+ import_node_fs40 = require("fs");
15302
+ import_node_path40 = require("path");
15099
15303
  init_worktree_labels();
15100
15304
  init_paths();
15101
15305
  EMPTY = {
@@ -15140,7 +15344,7 @@ function safeScriptToken(scriptName) {
15140
15344
  return token || "dev";
15141
15345
  }
15142
15346
  function runLogPath(key) {
15143
- return (0, import_node_path40.join)(threadsDir(), `${key}.run.log.json`);
15347
+ return (0, import_node_path41.join)(threadsDir(), `${key}.run.log.json`);
15144
15348
  }
15145
15349
  function runLogKeyForWorktree(worktreePath, scriptName) {
15146
15350
  const norm = normalizeWorktreePath(worktreePath);
@@ -15168,7 +15372,7 @@ function persistNow2(key) {
15168
15372
  const mem = memory2.get(key);
15169
15373
  if (!mem) return;
15170
15374
  try {
15171
- (0, import_node_fs40.writeFileSync)(runLogPath(key), `${JSON.stringify(materialize2(mem))}
15375
+ (0, import_node_fs41.writeFileSync)(runLogPath(key), `${JSON.stringify(materialize2(mem))}
15172
15376
  `, "utf8");
15173
15377
  } catch {
15174
15378
  }
@@ -15185,9 +15389,9 @@ function schedulePersist2(key) {
15185
15389
  }
15186
15390
  function loadFromDisk2(key) {
15187
15391
  const path = runLogPath(key);
15188
- if (!(0, import_node_fs40.existsSync)(path)) return null;
15392
+ if (!(0, import_node_fs41.existsSync)(path)) return null;
15189
15393
  try {
15190
- const raw = JSON.parse((0, import_node_fs40.readFileSync)(path, "utf8"));
15394
+ const raw = JSON.parse((0, import_node_fs41.readFileSync)(path, "utf8"));
15191
15395
  return {
15192
15396
  output: typeof raw.output === "string" ? raw.output : "",
15193
15397
  running: Boolean(raw.running),
@@ -15245,13 +15449,13 @@ function finishRunLog(key, exitCode) {
15245
15449
  function flushRunLog(key) {
15246
15450
  persistNow2(key);
15247
15451
  }
15248
- var import_node_crypto9, import_node_fs40, import_node_path40, EMPTY2, MAX_RUN_LOG_CHARS, DEFAULT_RUN_LOG_TAIL_CHARS, memory2, persistTimers2, PERSIST_DEBOUNCE_MS2;
15452
+ var import_node_crypto9, import_node_fs41, import_node_path41, EMPTY2, MAX_RUN_LOG_CHARS, DEFAULT_RUN_LOG_TAIL_CHARS, memory2, persistTimers2, PERSIST_DEBOUNCE_MS2;
15249
15453
  var init_run_log = __esm({
15250
15454
  "src/store/run-log.ts"() {
15251
15455
  "use strict";
15252
15456
  import_node_crypto9 = require("crypto");
15253
- import_node_fs40 = require("fs");
15254
- import_node_path40 = require("path");
15457
+ import_node_fs41 = require("fs");
15458
+ import_node_path41 = require("path");
15255
15459
  init_worktree_labels();
15256
15460
  init_setup_log();
15257
15461
  init_paths();
@@ -15280,9 +15484,9 @@ async function findOrphanWorktrees(repoPaths) {
15280
15484
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
15281
15485
  );
15282
15486
  const homeRoot = sideboardWorkspacesDir();
15283
- if ((0, import_node_fs41.existsSync)(homeRoot)) {
15487
+ if ((0, import_node_fs42.existsSync)(homeRoot)) {
15284
15488
  try {
15285
- for (const entry of (0, import_node_fs41.readdirSync)(homeRoot, { withFileTypes: true })) {
15489
+ for (const entry of (0, import_node_fs42.readdirSync)(homeRoot, { withFileTypes: true })) {
15286
15490
  if (!entry.isDirectory()) continue;
15287
15491
  void entry;
15288
15492
  }
@@ -15292,7 +15496,7 @@ async function findOrphanWorktrees(repoPaths) {
15292
15496
  const orphans = [];
15293
15497
  const seen = /* @__PURE__ */ new Set();
15294
15498
  for (const repoPath of repos) {
15295
- if (!repoPath || !(0, import_node_fs41.existsSync)(repoPath)) continue;
15499
+ if (!repoPath || !(0, import_node_fs42.existsSync)(repoPath)) continue;
15296
15500
  try {
15297
15501
  const wts = await listWorktrees(repoPath);
15298
15502
  for (const wt of wts) {
@@ -15303,7 +15507,7 @@ async function findOrphanWorktrees(repoPaths) {
15303
15507
  seen.add(path);
15304
15508
  let mtimeMs = 0;
15305
15509
  try {
15306
- mtimeMs = (0, import_node_fs41.statSync)(path).mtimeMs;
15510
+ mtimeMs = (0, import_node_fs42.statSync)(path).mtimeMs;
15307
15511
  } catch {
15308
15512
  mtimeMs = 0;
15309
15513
  }
@@ -15313,16 +15517,16 @@ async function findOrphanWorktrees(repoPaths) {
15313
15517
  }
15314
15518
  try {
15315
15519
  const root = worktreesRoot(repoPath);
15316
- if ((0, import_node_fs41.existsSync)(root)) {
15317
- for (const entry of (0, import_node_fs41.readdirSync)(root, { withFileTypes: true })) {
15520
+ if ((0, import_node_fs42.existsSync)(root)) {
15521
+ for (const entry of (0, import_node_fs42.readdirSync)(root, { withFileTypes: true })) {
15318
15522
  if (!entry.isDirectory()) continue;
15319
- const path = (0, import_node_path41.join)(root, entry.name).replace(/\/$/, "");
15523
+ const path = (0, import_node_path42.join)(root, entry.name).replace(/\/$/, "");
15320
15524
  if (known.has(path) || seen.has(path)) continue;
15321
- if (!(0, import_node_fs41.existsSync)((0, import_node_path41.join)(path, ".git"))) continue;
15525
+ if (!(0, import_node_fs42.existsSync)((0, import_node_path42.join)(path, ".git"))) continue;
15322
15526
  seen.add(path);
15323
15527
  let mtimeMs = 0;
15324
15528
  try {
15325
- mtimeMs = (0, import_node_fs41.statSync)(path).mtimeMs;
15529
+ mtimeMs = (0, import_node_fs42.statSync)(path).mtimeMs;
15326
15530
  } catch {
15327
15531
  mtimeMs = Date.now();
15328
15532
  }
@@ -15374,12 +15578,12 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
15374
15578
  const elapsed = Date.now() - Date.parse(last);
15375
15579
  return elapsed >= intervalHours * 36e5;
15376
15580
  }
15377
- var import_node_fs41, import_node_path41;
15581
+ var import_node_fs42, import_node_path42;
15378
15582
  var init_orphan_cleanup = __esm({
15379
15583
  "src/git/orphan-cleanup.ts"() {
15380
15584
  "use strict";
15381
- import_node_fs41 = require("fs");
15382
- import_node_path41 = require("path");
15585
+ import_node_fs42 = require("fs");
15586
+ import_node_path42 = require("path");
15383
15587
  init_worktree();
15384
15588
  init_thread_store();
15385
15589
  init_paths();
@@ -15554,12 +15758,12 @@ async function cloneRepoIntoSideboard(opts) {
15554
15758
  if (!url) throw new Error("Clone URL is required");
15555
15759
  let name = opts.name?.trim();
15556
15760
  if (!name) {
15557
- const leaf = (0, import_node_path42.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
15761
+ const leaf = (0, import_node_path43.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
15558
15762
  name = leaf || "repo";
15559
15763
  }
15560
15764
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
15561
- const dest = (0, import_node_path42.join)(sideboardReposDir(), name);
15562
- if ((0, import_node_fs42.existsSync)(dest)) {
15765
+ const dest = (0, import_node_path43.join)(sideboardReposDir(), name);
15766
+ if ((0, import_node_fs43.existsSync)(dest)) {
15563
15767
  const repoPath2 = await resolveRepoRoot(dest);
15564
15768
  const workspace2 = await ensureWorkspace(repoPath2);
15565
15769
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -15574,12 +15778,12 @@ async function cloneRepoIntoSideboard(opts) {
15574
15778
  const workspace = await ensureWorkspace(repoPath);
15575
15779
  return { repoPath, workspace };
15576
15780
  }
15577
- var import_node_fs42, import_node_path42, import_execa6;
15781
+ var import_node_fs43, import_node_path43, import_execa6;
15578
15782
  var init_clone_repo = __esm({
15579
15783
  "src/git/clone-repo.ts"() {
15580
15784
  "use strict";
15581
- import_node_fs42 = require("fs");
15582
- import_node_path42 = require("path");
15785
+ import_node_fs43 = require("fs");
15786
+ import_node_path43 = require("path");
15583
15787
  import_execa6 = require("execa");
15584
15788
  init_paths();
15585
15789
  init_workspaces();
@@ -15599,11 +15803,11 @@ var init_thread = __esm({
15599
15803
 
15600
15804
  // src/store/desktop-host.ts
15601
15805
  function desktopHostPidPath() {
15602
- return (0, import_node_path43.join)(appDataDir(), "desktop-host.pid");
15806
+ return (0, import_node_path44.join)(appDataDir(), "desktop-host.pid");
15603
15807
  }
15604
15808
  function readDesktopHostPid() {
15605
15809
  try {
15606
- const pid = Number.parseInt((0, import_node_fs43.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
15810
+ const pid = Number.parseInt((0, import_node_fs44.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
15607
15811
  if (!Number.isFinite(pid) || pid <= 0) return null;
15608
15812
  return pid;
15609
15813
  } catch {
@@ -15629,12 +15833,12 @@ function thisProcessShouldDrainAgentQueues() {
15629
15833
  if (isThisProcessDesktopHost()) return true;
15630
15834
  return !isDesktopHostAlive();
15631
15835
  }
15632
- var import_node_fs43, import_node_path43;
15836
+ var import_node_fs44, import_node_path44;
15633
15837
  var init_desktop_host = __esm({
15634
15838
  "src/store/desktop-host.ts"() {
15635
15839
  "use strict";
15636
- import_node_fs43 = require("fs");
15637
- import_node_path43 = require("path");
15840
+ import_node_fs44 = require("fs");
15841
+ import_node_path44 = require("path");
15638
15842
  init_paths();
15639
15843
  }
15640
15844
  });
@@ -15760,24 +15964,24 @@ function jobTreeAlive(pid) {
15760
15964
  return jobAlive(pid) || processGroupAlive(pid);
15761
15965
  }
15762
15966
  function readIntFile(file) {
15763
- if (!(0, import_node_fs44.existsSync)(file)) return null;
15764
- const n = Number.parseInt((0, import_node_fs44.readFileSync)(file, "utf8").trim(), 10);
15967
+ if (!(0, import_node_fs45.existsSync)(file)) return null;
15968
+ const n = Number.parseInt((0, import_node_fs45.readFileSync)(file, "utf8").trim(), 10);
15765
15969
  return Number.isInteger(n) ? n : null;
15766
15970
  }
15767
15971
  function jobDir(root, id, legacy = false) {
15768
- return (0, import_node_path44.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
15972
+ return (0, import_node_path45.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
15769
15973
  }
15770
15974
  function resolveJobDir(root, id) {
15771
15975
  const modern = jobDir(root, id, false);
15772
- if ((0, import_node_fs44.existsSync)(modern)) return modern;
15976
+ if ((0, import_node_fs45.existsSync)(modern)) return modern;
15773
15977
  const legacy = jobDir(root, id, true);
15774
- if ((0, import_node_fs44.existsSync)(legacy)) return legacy;
15978
+ if ((0, import_node_fs45.existsSync)(legacy)) return legacy;
15775
15979
  return modern;
15776
15980
  }
15777
15981
  function listJobIdsIn(root, rel) {
15778
- const dir = (0, import_node_path44.join)(root, rel);
15779
- if (!(0, import_node_fs44.existsSync)(dir)) return [];
15780
- return (0, import_node_fs44.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
15982
+ const dir = (0, import_node_path45.join)(root, rel);
15983
+ if (!(0, import_node_fs45.existsSync)(dir)) return [];
15984
+ return (0, import_node_fs45.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
15781
15985
  }
15782
15986
  function listRunningDetachedJobs(worktreePath) {
15783
15987
  const root = worktreePath.trim();
@@ -15789,7 +15993,7 @@ function listRunningDetachedJobs(worktreePath) {
15789
15993
  const running = [];
15790
15994
  for (const id of ids) {
15791
15995
  const dir = resolveJobDir(root, id);
15792
- const pid = readIntFile((0, import_node_path44.join)(dir, "pid"));
15996
+ const pid = readIntFile((0, import_node_path45.join)(dir, "pid"));
15793
15997
  if (jobTreeAlive(pid)) running.push(id);
15794
15998
  }
15795
15999
  return running.sort();
@@ -15872,8 +16076,8 @@ function planJobContinue(opts) {
15872
16076
  return { action: "none" };
15873
16077
  }
15874
16078
  function tailProgress(logFile, maxLines = 12) {
15875
- if (!(0, import_node_fs44.existsSync)(logFile)) return "(no log yet)";
15876
- const lines = (0, import_node_fs44.readFileSync)(logFile, "utf8").split("\n");
16079
+ if (!(0, import_node_fs45.existsSync)(logFile)) return "(no log yet)";
16080
+ const lines = (0, import_node_fs45.readFileSync)(logFile, "utf8").split("\n");
15877
16081
  return lines.slice(-maxLines).join("\n");
15878
16082
  }
15879
16083
  function lastProgressLine(progress) {
@@ -15881,8 +16085,8 @@ function lastProgressLine(progress) {
15881
16085
  return last ? last.slice(0, 72) : void 0;
15882
16086
  }
15883
16087
  function readLogLines(file) {
15884
- if (!(0, import_node_fs44.existsSync)(file)) return [];
15885
- const lines = (0, import_node_fs44.readFileSync)(file, "utf8").split("\n");
16088
+ if (!(0, import_node_fs45.existsSync)(file)) return [];
16089
+ const lines = (0, import_node_fs45.readFileSync)(file, "utf8").split("\n");
15886
16090
  if (lines.length && lines[lines.length - 1] === "") lines.pop();
15887
16091
  return lines;
15888
16092
  }
@@ -15893,15 +16097,15 @@ function takeDelta(logFile, cursorFile) {
15893
16097
  return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
15894
16098
  }
15895
16099
  function snapshotJob(dir) {
15896
- const pid = readIntFile((0, import_node_path44.join)(dir, "pid"));
16100
+ const pid = readIntFile((0, import_node_path45.join)(dir, "pid"));
15897
16101
  const running = jobTreeAlive(pid);
15898
16102
  return {
15899
16103
  pid,
15900
16104
  running,
15901
- exitCode: readIntFile((0, import_node_path44.join)(dir, "exit")),
15902
- log: (0, import_node_path44.join)(dir, "log"),
15903
- cursor: (0, import_node_path44.join)(dir, "present.cursor"),
15904
- progress: tailProgress((0, import_node_path44.join)(dir, "log"))
16105
+ exitCode: readIntFile((0, import_node_path45.join)(dir, "exit")),
16106
+ log: (0, import_node_path45.join)(dir, "log"),
16107
+ cursor: (0, import_node_path45.join)(dir, "present.cursor"),
16108
+ progress: tailProgress((0, import_node_path45.join)(dir, "log"))
15905
16109
  };
15906
16110
  }
15907
16111
  function toResult(id, snap, extra) {
@@ -15910,8 +16114,8 @@ function toResult(id, snap, extra) {
15910
16114
  const stillRunning = snap.running && !ok;
15911
16115
  const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
15912
16116
  try {
15913
- (0, import_node_fs44.mkdirSync)((0, import_node_path44.dirname)(snap.cursor), { recursive: true });
15914
- (0, import_node_fs44.writeFileSync)(snap.cursor, `${nextCursor}
16117
+ (0, import_node_fs45.mkdirSync)((0, import_node_path45.dirname)(snap.cursor), { recursive: true });
16118
+ (0, import_node_fs45.writeFileSync)(snap.cursor, `${nextCursor}
15915
16119
  `);
15916
16120
  } catch {
15917
16121
  }
@@ -15932,7 +16136,7 @@ function toResult(id, snap, extra) {
15932
16136
  };
15933
16137
  }
15934
16138
  async function sleepMs(ms) {
15935
- await new Promise((resolve) => setTimeout(resolve, ms));
16139
+ await new Promise((resolve2) => setTimeout(resolve2, ms));
15936
16140
  }
15937
16141
  async function waitForDetachedJob(cwd, id, opts) {
15938
16142
  const jobId = sanitizeDetachedJobId(id);
@@ -15940,7 +16144,7 @@ async function waitForDetachedJob(cwd, id, opts) {
15940
16144
  const dir = resolveJobDir(root, jobId);
15941
16145
  const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
15942
16146
  const sleep = opts?.sleep ?? sleepMs;
15943
- if (!(0, import_node_fs44.existsSync)(dir)) {
16147
+ if (!(0, import_node_fs45.existsSync)(dir)) {
15944
16148
  return {
15945
16149
  stillRunning: false,
15946
16150
  ok: false,
@@ -15986,10 +16190,10 @@ function killProcessTree(pid, signal) {
15986
16190
  }
15987
16191
  function appendJobLog(logFile, line) {
15988
16192
  try {
15989
- (0, import_node_fs44.mkdirSync)((0, import_node_path44.dirname)(logFile), { recursive: true });
16193
+ (0, import_node_fs45.mkdirSync)((0, import_node_path45.dirname)(logFile), { recursive: true });
15990
16194
  const body = line.endsWith("\n") ? line : `${line}
15991
16195
  `;
15992
- (0, import_node_fs44.appendFileSync)(logFile, body);
16196
+ (0, import_node_fs45.appendFileSync)(logFile, body);
15993
16197
  } catch {
15994
16198
  }
15995
16199
  }
@@ -15999,7 +16203,7 @@ async function stopDetachedJob(cwd, id, opts) {
15999
16203
  const dir = resolveJobDir(root, jobId);
16000
16204
  const sleep = opts?.sleep ?? sleepMs;
16001
16205
  const why = opts?.reason?.trim() ?? "";
16002
- if (!(0, import_node_fs44.existsSync)(dir)) {
16206
+ if (!(0, import_node_fs45.existsSync)(dir)) {
16003
16207
  return {
16004
16208
  stillRunning: false,
16005
16209
  ok: false,
@@ -16035,10 +16239,10 @@ async function stopDetachedJob(cwd, id, opts) {
16035
16239
  killProcessTree(targetPid, "SIGKILL");
16036
16240
  await sleep(100);
16037
16241
  }
16038
- const exitFile = (0, import_node_path44.join)(dir, "exit");
16039
- if (!(0, import_node_fs44.existsSync)(exitFile)) {
16242
+ const exitFile = (0, import_node_path45.join)(dir, "exit");
16243
+ if (!(0, import_node_fs45.existsSync)(exitFile)) {
16040
16244
  try {
16041
- (0, import_node_fs44.writeFileSync)(exitFile, "1\n");
16245
+ (0, import_node_fs45.writeFileSync)(exitFile, "1\n");
16042
16246
  } catch {
16043
16247
  }
16044
16248
  }
@@ -16058,12 +16262,12 @@ async function stopDetachedJob(cwd, id, opts) {
16058
16262
  hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
16059
16263
  };
16060
16264
  }
16061
- var import_node_fs44, import_node_path44, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
16265
+ var import_node_fs45, import_node_path45, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
16062
16266
  var init_wait_for_job = __esm({
16063
16267
  "src/mcp/wait-for-job.ts"() {
16064
16268
  "use strict";
16065
- import_node_fs44 = require("fs");
16066
- import_node_path44 = require("path");
16269
+ import_node_fs45 = require("fs");
16270
+ import_node_path45 = require("path");
16067
16271
  init_workspace_scratch();
16068
16272
  init_wait_for_turn();
16069
16273
  MAX_JOB_CONTINUES = 8;
@@ -16798,14 +17002,14 @@ async function startAbleTimeOAuth(opts) {
16798
17002
  const pkce = createAbleTimePkce();
16799
17003
  const authorizeUrl = ableTimeOAuthAuthorizeUrl(clientId, state, pkce.challenge, host);
16800
17004
  const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
16801
- const code = await new Promise((resolve, reject) => {
17005
+ const code = await new Promise((resolve2, reject) => {
16802
17006
  let settled = false;
16803
17007
  const finish = (err, value) => {
16804
17008
  if (settled) return;
16805
17009
  settled = true;
16806
17010
  cleanup();
16807
17011
  if (err) reject(err);
16808
- else resolve(value);
17012
+ else resolve2(value);
16809
17013
  };
16810
17014
  const server = (0, import_node_http.createServer)((req, res) => {
16811
17015
  try {
@@ -18098,7 +18302,7 @@ function reuseLiveThread(input, repoPath, match) {
18098
18302
  }
18099
18303
  async function createThread(input, _onSetupLine) {
18100
18304
  const repoPath = await resolveRepoRoot(input.repoPath);
18101
- if (!(0, import_node_fs45.existsSync)(repoPath)) {
18305
+ if (!(0, import_node_fs46.existsSync)(repoPath)) {
18102
18306
  throw new Error(`Repo not found: ${repoPath}`);
18103
18307
  }
18104
18308
  const reused = reuseLiveThread(input, repoPath, {
@@ -18274,11 +18478,11 @@ async function createThread(input, _onSetupLine) {
18274
18478
  await ensureWorkspace(repoPath);
18275
18479
  return readThread(thread.id) ?? thread;
18276
18480
  }
18277
- var import_node_fs45;
18481
+ var import_node_fs46;
18278
18482
  var init_create = __esm({
18279
18483
  "src/threads/create.ts"() {
18280
18484
  "use strict";
18281
- import_node_fs45 = require("fs");
18485
+ import_node_fs46 = require("fs");
18282
18486
  init_detect();
18283
18487
  init_worktree();
18284
18488
  init_home_board();
@@ -18430,20 +18634,20 @@ function writeTurnLive(threadId, progress) {
18430
18634
  const path = threadLivePath(threadId);
18431
18635
  const tmp = `${path}.${process.pid}.tmp`;
18432
18636
  try {
18433
- (0, import_node_fs46.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
18434
- (0, import_node_fs46.renameSync)(tmp, path);
18637
+ (0, import_node_fs47.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
18638
+ (0, import_node_fs47.renameSync)(tmp, path);
18435
18639
  } catch {
18436
18640
  try {
18437
- (0, import_node_fs46.unlinkSync)(tmp);
18641
+ (0, import_node_fs47.unlinkSync)(tmp);
18438
18642
  } catch {
18439
18643
  }
18440
18644
  }
18441
18645
  }
18442
18646
  function readTurnLive(threadId) {
18443
18647
  const path = threadLivePath(threadId);
18444
- if (!(0, import_node_fs46.existsSync)(path)) return null;
18648
+ if (!(0, import_node_fs47.existsSync)(path)) return null;
18445
18649
  try {
18446
- const raw = JSON.parse((0, import_node_fs46.readFileSync)(path, "utf8"));
18650
+ const raw = JSON.parse((0, import_node_fs47.readFileSync)(path, "utf8"));
18447
18651
  if (!raw || typeof raw.summary !== "string") return null;
18448
18652
  return raw;
18449
18653
  } catch {
@@ -18455,17 +18659,17 @@ function clearTurnLive(threadId) {
18455
18659
  if (buf?.timer) clearTimeout(buf.timer);
18456
18660
  buffers.delete(threadId);
18457
18661
  const path = threadLivePath(threadId);
18458
- if (!(0, import_node_fs46.existsSync)(path)) return;
18662
+ if (!(0, import_node_fs47.existsSync)(path)) return;
18459
18663
  try {
18460
- (0, import_node_fs46.unlinkSync)(path);
18664
+ (0, import_node_fs47.unlinkSync)(path);
18461
18665
  } catch {
18462
18666
  }
18463
18667
  }
18464
- var import_node_fs46, buffers, FLUSH_MS, MAX_PARTS;
18668
+ var import_node_fs47, buffers, FLUSH_MS, MAX_PARTS;
18465
18669
  var init_turn_live = __esm({
18466
18670
  "src/store/turn-live.ts"() {
18467
18671
  "use strict";
18468
- import_node_fs46 = require("fs");
18672
+ import_node_fs47 = require("fs");
18469
18673
  init_message_parts();
18470
18674
  init_paths();
18471
18675
  buffers = /* @__PURE__ */ new Map();
@@ -18706,7 +18910,7 @@ var init_quota_failover = __esm({
18706
18910
  // src/threads/adopt.ts
18707
18911
  function thisModuleFile2() {
18708
18912
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
18709
- return cjsFile || process.argv[1] || (0, import_node_path45.join)(process.cwd(), "package.json");
18913
+ return cjsFile || process.argv[1] || (0, import_node_path46.join)(process.cwd(), "package.json");
18710
18914
  }
18711
18915
  function openReadonlySqlite(file) {
18712
18916
  const req = (0, import_node_module5.createRequire)(thisModuleFile2());
@@ -18724,21 +18928,21 @@ function mapAgentType(raw) {
18724
18928
  return null;
18725
18929
  }
18726
18930
  function resolveConductorCursorAgentId(workspacePath) {
18727
- if (!workspacePath || !(0, import_node_fs47.existsSync)(CURSOR_SDK_STORE)) return null;
18931
+ if (!workspacePath || !(0, import_node_fs48.existsSync)(CURSOR_SDK_STORE)) return null;
18728
18932
  const normalized = workspacePath.replace(/\/$/, "");
18729
18933
  let best = null;
18730
18934
  let hashes;
18731
18935
  try {
18732
- hashes = (0, import_node_fs47.readdirSync)(CURSOR_SDK_STORE);
18936
+ hashes = (0, import_node_fs48.readdirSync)(CURSOR_SDK_STORE);
18733
18937
  } catch {
18734
18938
  return null;
18735
18939
  }
18736
18940
  for (const hash of hashes) {
18737
- const agentsFile = (0, import_node_path45.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
18738
- if (!(0, import_node_fs47.existsSync)(agentsFile)) continue;
18941
+ const agentsFile = (0, import_node_path46.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
18942
+ if (!(0, import_node_fs48.existsSync)(agentsFile)) continue;
18739
18943
  let text7;
18740
18944
  try {
18741
- text7 = (0, import_node_fs47.readFileSync)(agentsFile, "utf8");
18945
+ text7 = (0, import_node_fs48.readFileSync)(agentsFile, "utf8");
18742
18946
  } catch {
18743
18947
  continue;
18744
18948
  }
@@ -18762,7 +18966,7 @@ function resolveConductorCursorAgentId(workspacePath) {
18762
18966
  return best?.agentId ?? null;
18763
18967
  }
18764
18968
  async function adoptThread(input) {
18765
- if (!(0, import_node_fs47.existsSync)(input.worktreePath)) {
18969
+ if (!(0, import_node_fs48.existsSync)(input.worktreePath)) {
18766
18970
  throw new Error(`Worktree not found: ${input.worktreePath}`);
18767
18971
  }
18768
18972
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -18788,18 +18992,18 @@ async function adoptThread(input) {
18788
18992
  return thread;
18789
18993
  }
18790
18994
  function listConductorWorkspaces() {
18791
- if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
18995
+ if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
18792
18996
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
18793
18997
  }
18794
- const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path45.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18795
- const snapshot = (0, import_node_path45.join)(tmp, "conductor.db");
18998
+ const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path46.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18999
+ const snapshot = (0, import_node_path46.join)(tmp, "conductor.db");
18796
19000
  try {
18797
- (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
19001
+ (0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
18798
19002
  for (const suffix of ["-wal", "-shm"]) {
18799
19003
  const src = `${CONDUCTOR_DB}${suffix}`;
18800
- if ((0, import_node_fs47.existsSync)(src)) {
19004
+ if ((0, import_node_fs48.existsSync)(src)) {
18801
19005
  try {
18802
- (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
19006
+ (0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
18803
19007
  } catch {
18804
19008
  }
18805
19009
  }
@@ -18875,22 +19079,22 @@ function listConductorWorkspaces() {
18875
19079
  db.close();
18876
19080
  }
18877
19081
  } finally {
18878
- (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
19082
+ (0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
18879
19083
  }
18880
19084
  }
18881
19085
  function importConductorWorkspace(workspaceId) {
18882
- if (!(0, import_node_fs47.existsSync)(CONDUCTOR_DB)) {
19086
+ if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
18883
19087
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
18884
19088
  }
18885
- const tmp = (0, import_node_fs47.mkdtempSync)((0, import_node_path45.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
18886
- const snapshot = (0, import_node_path45.join)(tmp, "conductor.db");
19089
+ const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path46.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
19090
+ const snapshot = (0, import_node_path46.join)(tmp, "conductor.db");
18887
19091
  try {
18888
- (0, import_node_fs47.copyFileSync)(CONDUCTOR_DB, snapshot);
19092
+ (0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
18889
19093
  for (const suffix of ["-wal", "-shm"]) {
18890
19094
  const src = `${CONDUCTOR_DB}${suffix}`;
18891
- if ((0, import_node_fs47.existsSync)(src)) {
19095
+ if ((0, import_node_fs48.existsSync)(src)) {
18892
19096
  try {
18893
- (0, import_node_fs47.copyFileSync)(src, `${snapshot}${suffix}`);
19097
+ (0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
18894
19098
  } catch {
18895
19099
  }
18896
19100
  }
@@ -18908,7 +19112,7 @@ function importConductorWorkspace(workspaceId) {
18908
19112
  ).get(workspaceId);
18909
19113
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
18910
19114
  const worktreePath = String(row.workspacePath);
18911
- if (!(0, import_node_fs47.existsSync)(worktreePath)) {
19115
+ if (!(0, import_node_fs48.existsSync)(worktreePath)) {
18912
19116
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
18913
19117
  }
18914
19118
  let sessionId = null;
@@ -18971,31 +19175,31 @@ function importConductorWorkspace(workspaceId) {
18971
19175
  db.close();
18972
19176
  }
18973
19177
  } finally {
18974
- (0, import_node_fs47.rmSync)(tmp, { recursive: true, force: true });
19178
+ (0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
18975
19179
  }
18976
19180
  }
18977
19181
  async function importConductorWorkspaceAsync(workspaceId) {
18978
19182
  return importConductorWorkspace(workspaceId);
18979
19183
  }
18980
- var import_node_child_process5, import_node_fs47, import_node_os14, import_node_path45, import_node_module5, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
19184
+ var import_node_child_process5, import_node_fs48, import_node_os14, import_node_path46, import_node_module5, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
18981
19185
  var init_adopt = __esm({
18982
19186
  "src/threads/adopt.ts"() {
18983
19187
  "use strict";
18984
19188
  import_node_child_process5 = require("child_process");
18985
- import_node_fs47 = require("fs");
19189
+ import_node_fs48 = require("fs");
18986
19190
  import_node_os14 = require("os");
18987
- import_node_path45 = require("path");
19191
+ import_node_path46 = require("path");
18988
19192
  import_node_module5 = require("module");
18989
19193
  init_worktree();
18990
19194
  init_thread_store();
18991
- CONDUCTOR_APP_SUPPORT = (0, import_node_path45.join)(
19195
+ CONDUCTOR_APP_SUPPORT = (0, import_node_path46.join)(
18992
19196
  process.env.HOME ?? "",
18993
19197
  "Library",
18994
19198
  "Application Support",
18995
19199
  "com.conductor.app"
18996
19200
  );
18997
- CONDUCTOR_DB = (0, import_node_path45.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
18998
- CURSOR_SDK_STORE = (0, import_node_path45.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
19201
+ CONDUCTOR_DB = (0, import_node_path46.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
19202
+ CURSOR_SDK_STORE = (0, import_node_path46.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
18999
19203
  }
19000
19204
  });
19001
19205
 
@@ -19062,7 +19266,7 @@ async function openStackLayer(input, _onSetupLine) {
19062
19266
  let createdWorktree = false;
19063
19267
  const trees = await listWorktrees(repoPath);
19064
19268
  const checkedOut = trees.find((w) => w.branch === branchName);
19065
- if (checkedOut?.path && (0, import_node_fs48.existsSync)(checkedOut.path)) {
19269
+ if (checkedOut?.path && (0, import_node_fs49.existsSync)(checkedOut.path)) {
19066
19270
  if (input.reuseExistingWorktree !== false) {
19067
19271
  worktreePath = checkedOut.path;
19068
19272
  } else {
@@ -19204,7 +19408,7 @@ async function initStackFromThread(input, onSetupLine) {
19204
19408
  async function createPrStack(input, onSetupLine) {
19205
19409
  await requireAgent(input.agent);
19206
19410
  const repoPath = await resolveRepoRoot(input.repoPath);
19207
- if (!(0, import_node_fs48.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
19411
+ if (!(0, import_node_fs49.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
19208
19412
  if (!input.branches.length) throw new Error("At least one branch name required");
19209
19413
  const status = await detectGhStack(repoPath);
19210
19414
  if (!status.available) throw new Error(status.reason);
@@ -19271,7 +19475,7 @@ async function createPrStack(input, onSetupLine) {
19271
19475
  }
19272
19476
  }
19273
19477
  const claimed = new Set(threads.map((t) => t.worktreePath));
19274
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs48.existsSync)(bootstrap.worktreePath)) {
19478
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs49.existsSync)(bootstrap.worktreePath)) {
19275
19479
  try {
19276
19480
  await removeWorktree(repoPath, bootstrap.worktreePath, {
19277
19481
  deleteBranch: bootstrap.branchName
@@ -19281,11 +19485,11 @@ async function createPrStack(input, onSetupLine) {
19281
19485
  }
19282
19486
  return { stack, threads, createdThreadIds };
19283
19487
  }
19284
- var import_node_fs48;
19488
+ var import_node_fs49;
19285
19489
  var init_stack_layers = __esm({
19286
19490
  "src/threads/stack-layers.ts"() {
19287
19491
  "use strict";
19288
- import_node_fs48 = require("fs");
19492
+ import_node_fs49 = require("fs");
19289
19493
  init_detect();
19290
19494
  init_run();
19291
19495
  init_stack();
@@ -19298,7 +19502,7 @@ var init_stack_layers = __esm({
19298
19502
 
19299
19503
  // src/diff/diff.ts
19300
19504
  async function inspectGitWorktree(worktreePath) {
19301
- if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) return "missing_worktree";
19505
+ if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) return "missing_worktree";
19302
19506
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
19303
19507
  reject: false
19304
19508
  });
@@ -19306,7 +19510,7 @@ async function inspectGitWorktree(worktreePath) {
19306
19510
  return "ok";
19307
19511
  }
19308
19512
  async function initializeGitRepository(worktreePath) {
19309
- if (!worktreePath || !(0, import_node_fs49.existsSync)(worktreePath)) {
19513
+ if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) {
19310
19514
  throw new Error("Worktree not found");
19311
19515
  }
19312
19516
  const status = await inspectGitWorktree(worktreePath);
@@ -19440,11 +19644,11 @@ new file mode 100644
19440
19644
  };
19441
19645
  }
19442
19646
  async function untrackedPatch(worktreePath, path, maxHunk) {
19443
- const abs = (0, import_node_path46.join)(worktreePath, path);
19647
+ const abs = (0, import_node_path47.join)(worktreePath, path);
19444
19648
  try {
19445
- const st = (0, import_node_fs49.statSync)(abs);
19649
+ const st = (0, import_node_fs50.statSync)(abs);
19446
19650
  if (st.isFile() && st.size > maxHunk) {
19447
- const buf = (0, import_node_fs49.readFileSync)(abs).subarray(0, maxHunk);
19651
+ const buf = (0, import_node_fs50.readFileSync)(abs).subarray(0, maxHunk);
19448
19652
  return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
19449
19653
  }
19450
19654
  } catch {
@@ -19911,9 +20115,9 @@ async function getDiff(worktreePath, repoPath, opts) {
19911
20115
  }
19912
20116
  function statWorktreePath(worktreePath, relativePath) {
19913
20117
  assertSafeRelativePath(relativePath);
19914
- const abs = (0, import_node_path46.join)(worktreePath, relativePath);
19915
- if (!(0, import_node_fs49.existsSync)(abs)) return "missing";
19916
- const st = (0, import_node_fs49.statSync)(abs);
20118
+ const abs = (0, import_node_path47.join)(worktreePath, relativePath);
20119
+ if (!(0, import_node_fs50.existsSync)(abs)) return "missing";
20120
+ const st = (0, import_node_fs50.statSync)(abs);
19917
20121
  if (st.isDirectory()) return "dir";
19918
20122
  if (st.isFile()) return "file";
19919
20123
  return "missing";
@@ -19942,8 +20146,8 @@ function isImageRelativePath(relativePath) {
19942
20146
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19943
20147
  assertSafeRelativePath(relativePath);
19944
20148
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
19945
- const abs = (0, import_node_path46.join)(worktreePath, relativePath);
19946
- const st = (0, import_node_fs49.statSync)(abs);
20149
+ const abs = (0, import_node_path47.join)(worktreePath, relativePath);
20150
+ const st = (0, import_node_fs50.statSync)(abs);
19947
20151
  if (!st.isFile()) {
19948
20152
  throw new Error(`Not a file: ${relativePath}`);
19949
20153
  }
@@ -19952,7 +20156,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19952
20156
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
19953
20157
  );
19954
20158
  }
19955
- const buf = (0, import_node_fs49.readFileSync)(abs);
20159
+ const buf = (0, import_node_fs50.readFileSync)(abs);
19956
20160
  return {
19957
20161
  path: relativePath,
19958
20162
  contentBase64: buf.toString("base64"),
@@ -19962,12 +20166,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
19962
20166
  function readWorktreeFile(worktreePath, relativePath, opts) {
19963
20167
  assertSafeRelativePath(relativePath);
19964
20168
  const maxBytes = opts?.maxBytes ?? 2e5;
19965
- const abs = (0, import_node_path46.join)(worktreePath, relativePath);
19966
- const st = (0, import_node_fs49.statSync)(abs);
20169
+ const abs = (0, import_node_path47.join)(worktreePath, relativePath);
20170
+ const st = (0, import_node_fs50.statSync)(abs);
19967
20171
  if (!st.isFile()) {
19968
20172
  throw new Error(`Not a file: ${relativePath}`);
19969
20173
  }
19970
- const buf = (0, import_node_fs49.readFileSync)(abs);
20174
+ const buf = (0, import_node_fs50.readFileSync)(abs);
19971
20175
  if (isImageRelativePath(relativePath)) {
19972
20176
  const maxImageBytes = Math.max(maxBytes, 15e6);
19973
20177
  const truncated2 = buf.length > maxImageBytes;
@@ -20010,9 +20214,9 @@ function assertSafeRelativePath(relativePath) {
20010
20214
  }
20011
20215
  function writeWorktreeFile(worktreePath, relativePath, content) {
20012
20216
  assertSafeRelativePath(relativePath);
20013
- const abs = (0, import_node_path46.join)(worktreePath, relativePath);
20014
- (0, import_node_fs49.mkdirSync)((0, import_node_path46.dirname)(abs), { recursive: true });
20015
- (0, import_node_fs49.writeFileSync)(abs, content, "utf8");
20217
+ const abs = (0, import_node_path47.join)(worktreePath, relativePath);
20218
+ (0, import_node_fs50.mkdirSync)((0, import_node_path47.dirname)(abs), { recursive: true });
20219
+ (0, import_node_fs50.writeFileSync)(abs, content, "utf8");
20016
20220
  return { path: relativePath };
20017
20221
  }
20018
20222
  async function getWorktreeDirtyStat(worktreePath) {
@@ -20052,12 +20256,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
20052
20256
  truncated: full.files.length > maxFiles
20053
20257
  };
20054
20258
  }
20055
- var import_node_fs49, import_node_path46, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
20259
+ var import_node_fs50, import_node_path47, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
20056
20260
  var init_diff = __esm({
20057
20261
  "src/diff/diff.ts"() {
20058
20262
  "use strict";
20059
- import_node_fs49 = require("fs");
20060
- import_node_path46 = require("path");
20263
+ import_node_fs50 = require("fs");
20264
+ import_node_path47 = require("path");
20061
20265
  init_run();
20062
20266
  init_worktree();
20063
20267
  mergeBaseCache = /* @__PURE__ */ new Map();
@@ -20414,7 +20618,7 @@ function parseFrontmatter(content) {
20414
20618
  }
20415
20619
  function readSkill(skillMd, source) {
20416
20620
  try {
20417
- const content = (0, import_node_fs50.readFileSync)(skillMd, "utf8");
20621
+ const content = (0, import_node_fs51.readFileSync)(skillMd, "utf8");
20418
20622
  const { name: fmName, description } = parseFrontmatter(content);
20419
20623
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
20420
20624
  const name = fmName || dirName;
@@ -20433,19 +20637,19 @@ function readSkill(skillMd, source) {
20433
20637
  }
20434
20638
  }
20435
20639
  function scanSkillsDir(dir, source, out) {
20436
- if (!(0, import_node_fs50.existsSync)(dir)) return;
20640
+ if (!(0, import_node_fs51.existsSync)(dir)) return;
20437
20641
  let entries;
20438
20642
  try {
20439
- entries = (0, import_node_fs50.readdirSync)(dir);
20643
+ entries = (0, import_node_fs51.readdirSync)(dir);
20440
20644
  } catch {
20441
20645
  return;
20442
20646
  }
20443
20647
  for (const entry of entries) {
20444
20648
  if (entry.startsWith(".")) continue;
20445
- const skillMd = (0, import_node_path47.join)(dir, entry, "SKILL.md");
20446
- if (!(0, import_node_fs50.existsSync)(skillMd)) continue;
20649
+ const skillMd = (0, import_node_path48.join)(dir, entry, "SKILL.md");
20650
+ if (!(0, import_node_fs51.existsSync)(skillMd)) continue;
20447
20651
  try {
20448
- if (!(0, import_node_fs50.statSync)(skillMd).isFile()) continue;
20652
+ if (!(0, import_node_fs51.statSync)(skillMd).isFile()) continue;
20449
20653
  } catch {
20450
20654
  continue;
20451
20655
  }
@@ -20454,24 +20658,24 @@ function scanSkillsDir(dir, source, out) {
20454
20658
  }
20455
20659
  }
20456
20660
  function scanClaudePluginSkills(pluginsRoot, out) {
20457
- if (!(0, import_node_fs50.existsSync)(pluginsRoot)) return;
20661
+ if (!(0, import_node_fs51.existsSync)(pluginsRoot)) return;
20458
20662
  const walk = (dir, depth, lookingForSkillsDir) => {
20459
20663
  if (depth > 7) return;
20460
20664
  let entries;
20461
20665
  try {
20462
- entries = (0, import_node_fs50.readdirSync)(dir);
20666
+ entries = (0, import_node_fs51.readdirSync)(dir);
20463
20667
  } catch {
20464
20668
  return;
20465
20669
  }
20466
20670
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
20467
- const skill = readSkill((0, import_node_path47.join)(dir, "SKILL.md"), "cli");
20671
+ const skill = readSkill((0, import_node_path48.join)(dir, "SKILL.md"), "cli");
20468
20672
  if (skill) out.push(skill);
20469
20673
  }
20470
20674
  for (const entry of entries) {
20471
20675
  if (entry === "node_modules" || entry === ".git") continue;
20472
- const full = (0, import_node_path47.join)(dir, entry);
20676
+ const full = (0, import_node_path48.join)(dir, entry);
20473
20677
  try {
20474
- if (!(0, import_node_fs50.statSync)(full).isDirectory()) continue;
20678
+ if (!(0, import_node_fs51.statSync)(full).isDirectory()) continue;
20475
20679
  } catch {
20476
20680
  continue;
20477
20681
  }
@@ -20489,17 +20693,17 @@ function discoverSkills(worktreePath) {
20489
20693
  const home = (0, import_node_os15.homedir)();
20490
20694
  const collected = [];
20491
20695
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
20492
- scanSkillsDir((0, import_node_path47.join)(worktreePath, rel), "workspace", collected);
20696
+ scanSkillsDir((0, import_node_path48.join)(worktreePath, rel), "workspace", collected);
20493
20697
  }
20494
20698
  for (const abs of [
20495
- (0, import_node_path47.join)(home, ".claude/skills"),
20496
- (0, import_node_path47.join)(home, ".cursor/skills"),
20497
- (0, import_node_path47.join)(home, ".sideboard/skills"),
20498
- (0, import_node_path47.join)(home, ".brightsy/skills")
20699
+ (0, import_node_path48.join)(home, ".claude/skills"),
20700
+ (0, import_node_path48.join)(home, ".cursor/skills"),
20701
+ (0, import_node_path48.join)(home, ".sideboard/skills"),
20702
+ (0, import_node_path48.join)(home, ".brightsy/skills")
20499
20703
  ]) {
20500
20704
  scanSkillsDir(abs, "user", collected);
20501
20705
  }
20502
- scanClaudePluginSkills((0, import_node_path47.join)(home, ".claude/plugins"), collected);
20706
+ scanClaudePluginSkills((0, import_node_path48.join)(home, ".claude/plugins"), collected);
20503
20707
  collected.push(...bundledSkills());
20504
20708
  const rank = {
20505
20709
  workspace: 0,
@@ -20525,7 +20729,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
20525
20729
  \u2026(truncated)` : body;
20526
20730
  }
20527
20731
  }
20528
- const raw = (0, import_node_fs50.readFileSync)(skillPath, "utf8");
20732
+ const raw = (0, import_node_fs51.readFileSync)(skillPath, "utf8");
20529
20733
  if (raw.startsWith("---")) {
20530
20734
  const end = raw.indexOf("\n---", 3);
20531
20735
  if (end >= 0) {
@@ -20539,13 +20743,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
20539
20743
 
20540
20744
  \u2026(truncated)` : raw;
20541
20745
  }
20542
- var import_node_fs50, import_node_os15, import_node_path47, BUNDLED_SKILL_PREFIX;
20746
+ var import_node_fs51, import_node_os15, import_node_path48, BUNDLED_SKILL_PREFIX;
20543
20747
  var init_discover = __esm({
20544
20748
  "src/skills/discover.ts"() {
20545
20749
  "use strict";
20546
- import_node_fs50 = require("fs");
20750
+ import_node_fs51 = require("fs");
20547
20751
  import_node_os15 = require("os");
20548
- import_node_path47 = require("path");
20752
+ import_node_path48 = require("path");
20549
20753
  init_long_running();
20550
20754
  BUNDLED_SKILL_PREFIX = "bundled:";
20551
20755
  }
@@ -20700,7 +20904,7 @@ function compiledModuleDir() {
20700
20904
  try {
20701
20905
  const url = import_meta4.url;
20702
20906
  if (typeof url === "string" && url.length > 0) {
20703
- return (0, import_node_path48.dirname)((0, import_node_url4.fileURLToPath)(url));
20907
+ return (0, import_node_path49.dirname)((0, import_node_url4.fileURLToPath)(url));
20704
20908
  }
20705
20909
  } catch {
20706
20910
  }
@@ -20708,8 +20912,8 @@ function compiledModuleDir() {
20708
20912
  }
20709
20913
  function detachedJobScriptIn(dir) {
20710
20914
  for (const name of DETACHED_JOB_FILENAMES) {
20711
- const script = (0, import_node_path48.join)(dir, "scripts", name);
20712
- if ((0, import_node_fs51.existsSync)(script)) return script;
20915
+ const script = (0, import_node_path49.join)(dir, "scripts", name);
20916
+ if ((0, import_node_fs52.existsSync)(script)) return script;
20713
20917
  }
20714
20918
  return null;
20715
20919
  }
@@ -20726,7 +20930,7 @@ function resolveDetachedJobScript() {
20726
20930
  for (let i = 0; i < 8; i++) {
20727
20931
  const candidate = detachedJobScriptIn(dir);
20728
20932
  if (candidate) return candidate;
20729
- const parent = (0, import_node_path48.dirname)(dir);
20933
+ const parent = (0, import_node_path49.dirname)(dir);
20730
20934
  if (parent === dir) break;
20731
20935
  dir = parent;
20732
20936
  }
@@ -20737,12 +20941,12 @@ function formatDetachedJobInvoke(scriptPath) {
20737
20941
  if (resolved) return `node ${JSON.stringify(resolved)}`;
20738
20942
  return "node scripts/detached-job.cjs";
20739
20943
  }
20740
- var import_node_fs51, import_node_path48, import_node_url4, import_meta4, DETACHED_JOB_FILENAMES;
20944
+ var import_node_fs52, import_node_path49, import_node_url4, import_meta4, DETACHED_JOB_FILENAMES;
20741
20945
  var init_detached_job_path = __esm({
20742
20946
  "src/skills/detached-job-path.ts"() {
20743
20947
  "use strict";
20744
- import_node_fs51 = require("fs");
20745
- import_node_path48 = require("path");
20948
+ import_node_fs52 = require("fs");
20949
+ import_node_path49 = require("path");
20746
20950
  import_node_url4 = require("url");
20747
20951
  init_packaged_runtime();
20748
20952
  import_meta4 = {};
@@ -20843,9 +21047,9 @@ function formatWorktreeDirective(thread, opts) {
20843
21047
  );
20844
21048
  } else {
20845
21049
  const slug = opts?.githubSlug ?? "<origin-owner/name>";
20846
- const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
21050
+ const resolve2 = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
20847
21051
  lines.push(
20848
- `- Prefer a draft PR first: \`gh pr create --draft -R ${slug}\` (update via \`gh pr edit -R ${slug}\`). Always pass \`-R\` \u2014 bare \`gh pr create\` may target upstream on dual-remote checkouts.${resolve} Mark ready for review only when asked. If GitHub rejects the body as too long, retry with a short \`--body-file\` \u2014 do not paste a changelog or diff into \`--body\`.`
21052
+ `- Prefer a draft PR first: \`gh pr create --draft -R ${slug}\` (update via \`gh pr edit -R ${slug}\`). Always pass \`-R\` \u2014 bare \`gh pr create\` may target upstream on dual-remote checkouts.${resolve2} Mark ready for review only when asked. If GitHub rejects the body as too long, retry with a short \`--body-file\` \u2014 do not paste a changelog or diff into \`--body\`.`
20849
21053
  );
20850
21054
  }
20851
21055
  lines.push(
@@ -20932,9 +21136,9 @@ function formatPrGateDirective() {
20932
21136
  }
20933
21137
  function formatProcessGuideDirective(opts) {
20934
21138
  const worktree = opts?.worktreePath?.trim();
20935
- const hasGraphSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path49.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
20936
- const hasReviewSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path49.join)(worktree, ".claude/skills/review/SKILL.md"));
20937
- const hasInstallSkill = !!worktree && (0, import_node_fs52.existsSync)((0, import_node_path49.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
21139
+ const hasGraphSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
21140
+ const hasReviewSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/review/SKILL.md"));
21141
+ const hasInstallSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
20938
21142
  return [
20939
21143
  "Process guides (recurring work only):",
20940
21144
  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,
@@ -20973,12 +21177,12 @@ function formatArtifactDirective() {
20973
21177
  function formatUiReminder() {
20974
21178
  return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. ask_user wakes the parent orchestrator; notify_orchestrator if blocked without a picker. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button) returns {url, port, preview} (SIDEBOARD_PORT \u2014 never guess :3000). preview=url \u2192 open url; preview=window \u2192 Electron window is the app, url is renderer/HMR only. list_run_scripts active[].url if already running; get_run_log for the Run-tab terminal; stop_dev_script to stop.";
20975
21179
  }
20976
- var import_node_fs52, import_node_path49, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
21180
+ var import_node_fs53, import_node_path50, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
20977
21181
  var init_instructions = __esm({
20978
21182
  "src/agents/instructions.ts"() {
20979
21183
  "use strict";
20980
- import_node_fs52 = require("fs");
20981
- import_node_path49 = require("path");
21184
+ import_node_fs53 = require("fs");
21185
+ import_node_path50 = require("path");
20982
21186
  init_git_auth_mode();
20983
21187
  init_branch_prefix();
20984
21188
  init_worktree_labels();
@@ -21202,40 +21406,40 @@ __export(plan_file_exports, {
21202
21406
  writePlanFile: () => writePlanFile
21203
21407
  });
21204
21408
  function ensureAttachmentsGitignore(worktreePath) {
21205
- const gitignoreAbs = (0, import_node_path50.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
21206
- if ((0, import_node_fs53.existsSync)(gitignoreAbs)) return;
21207
- (0, import_node_fs53.mkdirSync)((0, import_node_path50.dirname)(gitignoreAbs), { recursive: true });
21208
- (0, import_node_fs53.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
21409
+ const gitignoreAbs = (0, import_node_path51.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
21410
+ if ((0, import_node_fs54.existsSync)(gitignoreAbs)) return;
21411
+ (0, import_node_fs54.mkdirSync)((0, import_node_path51.dirname)(gitignoreAbs), { recursive: true });
21412
+ (0, import_node_fs54.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
21209
21413
  }
21210
21414
  function planFileAbs(worktreePath) {
21211
- return (0, import_node_path50.join)(worktreePath, PLAN_FILE_REL);
21415
+ return (0, import_node_path51.join)(worktreePath, PLAN_FILE_REL);
21212
21416
  }
21213
21417
  function readTextIfPresent2(abs) {
21214
- if (!(0, import_node_fs53.existsSync)(abs)) return null;
21418
+ if (!(0, import_node_fs54.existsSync)(abs)) return null;
21215
21419
  try {
21216
- const content = (0, import_node_fs53.readFileSync)(abs, "utf8");
21420
+ const content = (0, import_node_fs54.readFileSync)(abs, "utf8");
21217
21421
  return content.trim() ? content : null;
21218
21422
  } catch {
21219
21423
  return null;
21220
21424
  }
21221
21425
  }
21222
21426
  function readPlanFile(worktreePath) {
21223
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path50.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path50.join)(worktreePath, LEGACY_PLAN_FILE_REL));
21427
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path51.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path51.join)(worktreePath, LEGACY_PLAN_FILE_REL));
21224
21428
  }
21225
21429
  function writePlanFile(worktreePath, content) {
21226
21430
  ensureAttachmentsGitignore(worktreePath);
21227
21431
  const abs = planFileAbs(worktreePath);
21228
- (0, import_node_fs53.mkdirSync)((0, import_node_path50.dirname)(abs), { recursive: true });
21432
+ (0, import_node_fs54.mkdirSync)((0, import_node_path51.dirname)(abs), { recursive: true });
21229
21433
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
21230
- (0, import_node_fs53.writeFileSync)(abs, body, "utf8");
21434
+ (0, import_node_fs54.writeFileSync)(abs, body, "utf8");
21231
21435
  return PLAN_FILE_REL;
21232
21436
  }
21233
- var import_node_fs53, import_node_path50;
21437
+ var import_node_fs54, import_node_path51;
21234
21438
  var init_plan_file = __esm({
21235
21439
  "src/plan/plan-file.ts"() {
21236
21440
  "use strict";
21237
- import_node_fs53 = require("fs");
21238
- import_node_path50 = require("path");
21441
+ import_node_fs54 = require("fs");
21442
+ import_node_path51 = require("path");
21239
21443
  init_workspace_scratch();
21240
21444
  init_plan_present();
21241
21445
  init_plan_present();
@@ -21295,7 +21499,7 @@ function setCaffeinateHoldHooks(next) {
21295
21499
  hooks = next;
21296
21500
  }
21297
21501
  function caffeinateHoldPath() {
21298
- return (0, import_node_path51.join)(appDataDir(), "caffeinate-hold.json");
21502
+ return (0, import_node_path52.join)(appDataDir(), "caffeinate-hold.json");
21299
21503
  }
21300
21504
  function processAlive(pid) {
21301
21505
  if (hooks.processAlive) return hooks.processAlive(pid);
@@ -21329,9 +21533,9 @@ function uniqueIds(ids) {
21329
21533
  }
21330
21534
  function readHold() {
21331
21535
  const path = caffeinateHoldPath();
21332
- if (!(0, import_node_fs54.existsSync)(path)) return null;
21536
+ if (!(0, import_node_fs55.existsSync)(path)) return null;
21333
21537
  try {
21334
- const parsed = JSON.parse((0, import_node_fs54.readFileSync)(path, "utf8"));
21538
+ const parsed = JSON.parse((0, import_node_fs55.readFileSync)(path, "utf8"));
21335
21539
  if (typeof parsed?.pid === "number" && parsed.pid > 0) {
21336
21540
  return {
21337
21541
  pid: parsed.pid,
@@ -21353,7 +21557,7 @@ function writeHold(pid, threadIds) {
21353
21557
  }
21354
21558
  function clearHold() {
21355
21559
  try {
21356
- (0, import_node_fs54.unlinkSync)(caffeinateHoldPath());
21560
+ (0, import_node_fs55.unlinkSync)(caffeinateHoldPath());
21357
21561
  } catch {
21358
21562
  }
21359
21563
  }
@@ -21438,13 +21642,13 @@ function releaseCaffeinateHoldForThread(threadId) {
21438
21642
  }
21439
21643
  return setCaffeinateHold(false, { threadId: id });
21440
21644
  }
21441
- var import_node_child_process6, import_node_fs54, import_node_path51, hooks;
21645
+ var import_node_child_process6, import_node_fs55, import_node_path52, hooks;
21442
21646
  var init_caffeinate_hold = __esm({
21443
21647
  "src/store/caffeinate-hold.ts"() {
21444
21648
  "use strict";
21445
21649
  import_node_child_process6 = require("child_process");
21446
- import_node_fs54 = require("fs");
21447
- import_node_path51 = require("path");
21650
+ import_node_fs55 = require("fs");
21651
+ import_node_path52 = require("path");
21448
21652
  init_paths();
21449
21653
  init_private_file();
21450
21654
  hooks = {};
@@ -21453,7 +21657,7 @@ var init_caffeinate_hold = __esm({
21453
21657
 
21454
21658
  // src/store/schedules.ts
21455
21659
  function schedulesPath() {
21456
- return (0, import_node_path52.join)(appDataDir(), "schedules.json");
21660
+ return (0, import_node_path53.join)(appDataDir(), "schedules.json");
21457
21661
  }
21458
21662
  function parseDurationMs(every) {
21459
21663
  const m = every.trim().match(DURATION_RE);
@@ -21553,9 +21757,9 @@ function normalizeTask(raw) {
21553
21757
  }
21554
21758
  function readAll2() {
21555
21759
  const path = schedulesPath();
21556
- if (!(0, import_node_fs55.existsSync)(path)) return [];
21760
+ if (!(0, import_node_fs56.existsSync)(path)) return [];
21557
21761
  try {
21558
- const parsed = JSON.parse((0, import_node_fs55.readFileSync)(path, "utf8"));
21762
+ const parsed = JSON.parse((0, import_node_fs56.readFileSync)(path, "utf8"));
21559
21763
  if (!Array.isArray(parsed)) return [];
21560
21764
  return parsed.map((row) => {
21561
21765
  try {
@@ -21667,13 +21871,13 @@ function recordScheduleRun(id, result) {
21667
21871
  writeAll2(rows);
21668
21872
  return next;
21669
21873
  }
21670
- var import_node_crypto12, import_node_fs55, import_node_path52, import_croner, DURATION_RE, UNIT_MS;
21874
+ var import_node_crypto12, import_node_fs56, import_node_path53, import_croner, DURATION_RE, UNIT_MS;
21671
21875
  var init_schedules = __esm({
21672
21876
  "src/store/schedules.ts"() {
21673
21877
  "use strict";
21674
21878
  import_node_crypto12 = require("crypto");
21675
- import_node_fs55 = require("fs");
21676
- import_node_path52 = require("path");
21879
+ import_node_fs56 = require("fs");
21880
+ import_node_path53 = require("path");
21677
21881
  import_croner = require("croner");
21678
21882
  init_orchestrator_capable();
21679
21883
  init_paths();
@@ -21759,14 +21963,14 @@ function armOne(schedule) {
21759
21963
  if (!schedule.enabled) return;
21760
21964
  const at = new Date(schedule.nextRunAt);
21761
21965
  if (Number.isNaN(at.getTime())) return;
21762
- const delay = Math.max(0, at.getTime() - Date.now());
21763
- if (delay <= 250) {
21966
+ const delay2 = Math.max(0, at.getTime() - Date.now());
21967
+ if (delay2 <= 250) {
21764
21968
  void fireSchedule(schedule.id).then(() => {
21765
21969
  if (isThisProcessDesktopHost()) armSchedules();
21766
21970
  });
21767
21971
  return;
21768
21972
  }
21769
- const capped = Math.min(delay, SET_TIMEOUT_MAX);
21973
+ const capped = Math.min(delay2, SET_TIMEOUT_MAX);
21770
21974
  const timer = setTimeout(() => {
21771
21975
  timers.delete(schedule.id);
21772
21976
  const live = getSchedule(schedule.id);
@@ -21829,9 +22033,9 @@ function recoverFinishedCursorRun(opts) {
21829
22033
  return best;
21830
22034
  }
21831
22035
  function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
21832
- if (!(0, import_node_fs56.existsSync)(runsPath)) return null;
22036
+ if (!(0, import_node_fs57.existsSync)(runsPath)) return null;
21833
22037
  try {
21834
- const lines = (0, import_node_fs56.readFileSync)(runsPath, "utf8").split("\n");
22038
+ const lines = (0, import_node_fs57.readFileSync)(runsPath, "utf8").split("\n");
21835
22039
  let best = null;
21836
22040
  for (const line of lines) {
21837
22041
  const trimmed = line.trim();
@@ -21857,11 +22061,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
21857
22061
  return null;
21858
22062
  }
21859
22063
  }
21860
- var import_node_fs56;
22064
+ var import_node_fs57;
21861
22065
  var init_cursor_recover = __esm({
21862
22066
  "src/agents/cursor-recover.ts"() {
21863
22067
  "use strict";
21864
- import_node_fs56 = require("fs");
22068
+ import_node_fs57 = require("fs");
21865
22069
  init_cursor_store();
21866
22070
  }
21867
22071
  });
@@ -22015,7 +22219,7 @@ async function startOrchestration(opts) {
22015
22219
  }
22016
22220
  return updated;
22017
22221
  }
22018
- var import_node_events, import_node_crypto13, import_node_fs57, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
22222
+ var import_node_events, import_node_crypto13, import_node_fs58, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
22019
22223
  var init_orchestrator = __esm({
22020
22224
  "src/orchestrator/orchestrator.ts"() {
22021
22225
  "use strict";
@@ -22023,7 +22227,7 @@ var init_orchestrator = __esm({
22023
22227
  init_injected_notices();
22024
22228
  init_task_state();
22025
22229
  import_node_crypto13 = require("crypto");
22026
- import_node_fs57 = require("fs");
22230
+ import_node_fs58 = require("fs");
22027
22231
  init_error_detail();
22028
22232
  init_run();
22029
22233
  init_stale_lock();
@@ -22202,7 +22406,7 @@ var init_orchestrator = __esm({
22202
22406
  this.lightReconcileAt.set(repoPath, Date.now());
22203
22407
  for (const thread of listThreads()) {
22204
22408
  if (isGlobalThread(thread) || thread.repoPath !== repoPath) continue;
22205
- if (!(0, import_node_fs57.existsSync)(thread.worktreePath)) {
22409
+ if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
22206
22410
  setStatus(thread.id, "broken", "Worktree missing on disk");
22207
22411
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
22208
22412
  }
@@ -22231,7 +22435,7 @@ var init_orchestrator = __esm({
22231
22435
  }
22232
22436
  continue;
22233
22437
  }
22234
- if (!(0, import_node_fs57.existsSync)(thread.worktreePath)) {
22438
+ if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
22235
22439
  setStatus(thread.id, "broken", "Worktree missing on disk");
22236
22440
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
22237
22441
  continue;
@@ -22399,8 +22603,8 @@ var init_orchestrator = __esm({
22399
22603
  scheduleQuotaResume(threadId, resumeAt) {
22400
22604
  this.clearQuotaResumeTimer(threadId);
22401
22605
  updateThread(threadId, { quotaResumeAt: resumeAt.toISOString() });
22402
- const delay = Math.max(5e3, resumeAt.getTime() - Date.now());
22403
- const capped = Math.min(delay, 2147483647);
22606
+ const delay2 = Math.max(5e3, resumeAt.getTime() - Date.now());
22607
+ const capped = Math.min(delay2, 2147483647);
22404
22608
  const timer = setTimeout(() => {
22405
22609
  this.quotaResumeTimers.delete(threadId);
22406
22610
  void this.resumeAfterQuotaWait(threadId);
@@ -23455,6 +23659,7 @@ var init_orchestrator = __esm({
23455
23659
  return { port: shared.devPort, scriptName: resolvedName, ports: [shared.devPort] };
23456
23660
  }
23457
23661
  }
23662
+ const preferredPorts = active?.ports?.length ? active.ports : active?.port != null ? [active.port] : void 0;
23458
23663
  if (active && !existing) {
23459
23664
  killListenersOnPorts(collectActiveRunPorts([active]));
23460
23665
  this.syncWorktreeRuns(
@@ -23493,7 +23698,7 @@ var init_orchestrator = __esm({
23493
23698
  thread.repoPath,
23494
23699
  thread.worktreePath,
23495
23700
  runOutput.push,
23496
- { scriptName: resolvedName }
23701
+ { scriptName: resolvedName, preferredPorts }
23497
23702
  );
23498
23703
  } catch (err) {
23499
23704
  runOutput.flush();
@@ -23942,7 +24147,7 @@ var init_orchestrator = __esm({
23942
24147
  return thread;
23943
24148
  }
23944
24149
  const start = Date.now();
23945
- return new Promise((resolve, reject) => {
24150
+ return new Promise((resolve2, reject) => {
23946
24151
  let settled = false;
23947
24152
  let timer;
23948
24153
  const finish = (fn) => {
@@ -23960,7 +24165,7 @@ var init_orchestrator = __esm({
23960
24165
  finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
23961
24166
  return;
23962
24167
  }
23963
- finish(() => resolve(latest));
24168
+ finish(() => resolve2(latest));
23964
24169
  return;
23965
24170
  }
23966
24171
  if (event.type === "status_changed") {
@@ -23970,7 +24175,7 @@ var init_orchestrator = __esm({
23970
24175
  return;
23971
24176
  }
23972
24177
  if (!["running", "queued"].includes(latest.status)) {
23973
- finish(() => resolve(latest));
24178
+ finish(() => resolve2(latest));
23974
24179
  }
23975
24180
  }
23976
24181
  });
@@ -23982,12 +24187,12 @@ var init_orchestrator = __esm({
23982
24187
  }
23983
24188
  const current = this.healStaleReportedActivity(raw);
23984
24189
  if (!this.threadLooksLive(current)) {
23985
- finish(() => resolve(current));
24190
+ finish(() => resolve2(current));
23986
24191
  return;
23987
24192
  }
23988
24193
  if (Date.now() - start > timeoutMs) {
23989
24194
  if (opts?.resolveIfStillRunning) {
23990
- finish(() => resolve(current));
24195
+ finish(() => resolve2(current));
23991
24196
  } else {
23992
24197
  finish(() => reject(new Error("wait_for_turn timed out")));
23993
24198
  }
@@ -24579,7 +24784,7 @@ var init_orchestrator = __esm({
24579
24784
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
24580
24785
  return restored2;
24581
24786
  }
24582
- if (!(0, import_node_fs57.existsSync)(thread.worktreePath)) {
24787
+ if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
24583
24788
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
24584
24789
  throw new Error(
24585
24790
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
@@ -24663,7 +24868,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
24663
24868
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
24664
24869
  var import_zod9 = require("zod");
24665
24870
  var import_node_crypto16 = require("crypto");
24666
- var import_node_path58 = require("path");
24871
+ var import_node_path59 = require("path");
24667
24872
  init_orchestrator();
24668
24873
  init_task_state();
24669
24874
  init_worktree();
@@ -26778,8 +26983,8 @@ ${link}` : link;
26778
26983
  }
26779
26984
 
26780
26985
  // src/slack/outbound-watch.ts
26781
- var import_node_fs59 = require("fs");
26782
- var import_node_path55 = require("path");
26986
+ var import_node_fs60 = require("fs");
26987
+ var import_node_path56 = require("path");
26783
26988
  init_paths();
26784
26989
  init_private_file();
26785
26990
  init_secure_file();
@@ -26787,19 +26992,19 @@ init_thread_store();
26787
26992
  init_injected_notices();
26788
26993
 
26789
26994
  // src/slack/reply-target.ts
26790
- var import_node_fs58 = require("fs");
26791
- var import_node_path53 = require("path");
26995
+ var import_node_fs59 = require("fs");
26996
+ var import_node_path54 = require("path");
26792
26997
  init_paths();
26793
26998
  init_private_file();
26794
26999
  init_secure_file();
26795
27000
  function storePath2() {
26796
- return (0, import_node_path53.join)(appDataDir(), "slack-reply-to.json");
27001
+ return (0, import_node_path54.join)(appDataDir(), "slack-reply-to.json");
26797
27002
  }
26798
27003
  function readStore2() {
26799
27004
  const path = storePath2();
26800
- if (!(0, import_node_fs58.existsSync)(path)) return {};
27005
+ if (!(0, import_node_fs59.existsSync)(path)) return {};
26801
27006
  try {
26802
- const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs58.readFileSync)(path, "utf8"));
27007
+ const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs59.readFileSync)(path, "utf8"));
26803
27008
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
26804
27009
  } catch {
26805
27010
  return {};
@@ -26810,11 +27015,11 @@ function getSlackReplyTarget(threadId) {
26810
27015
  }
26811
27016
 
26812
27017
  // src/slack/workspaces.ts
26813
- var import_node_path54 = require("path");
27018
+ var import_node_path55 = require("path");
26814
27019
  init_paths();
26815
27020
  init_secure_file();
26816
27021
  function storePath3() {
26817
- return (0, import_node_path54.join)(appDataDir(), "slack-workspaces.json");
27022
+ return (0, import_node_path55.join)(appDataDir(), "slack-workspaces.json");
26818
27023
  }
26819
27024
  function readStore3() {
26820
27025
  try {
@@ -26884,7 +27089,7 @@ var POLL_INTERVAL_MS = 12e3;
26884
27089
  var lastPollMs = 0;
26885
27090
  var nameCache = /* @__PURE__ */ new Map();
26886
27091
  function storePath4() {
26887
- return (0, import_node_path55.join)(appDataDir(), "slack-outbound-watch.json");
27092
+ return (0, import_node_path56.join)(appDataDir(), "slack-outbound-watch.json");
26888
27093
  }
26889
27094
  function watchId(teamId, channelId, ts) {
26890
27095
  return `${teamId}:${channelId}:${ts}`;
@@ -26897,9 +27102,9 @@ function tsNewer(a, b) {
26897
27102
  }
26898
27103
  function readStore4() {
26899
27104
  const path = storePath4();
26900
- if (!(0, import_node_fs59.existsSync)(path)) return [];
27105
+ if (!(0, import_node_fs60.existsSync)(path)) return [];
26901
27106
  try {
26902
- const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs59.readFileSync)(path, "utf8"));
27107
+ const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs60.readFileSync)(path, "utf8"));
26903
27108
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
26904
27109
  } catch {
26905
27110
  return [];
@@ -28641,27 +28846,27 @@ init_gh_errors();
28641
28846
  init_git_auth_mode();
28642
28847
 
28643
28848
  // src/board/load-home-board.ts
28644
- var import_node_fs61 = require("fs");
28645
- var import_node_path57 = require("path");
28849
+ var import_node_fs62 = require("fs");
28850
+ var import_node_path58 = require("path");
28646
28851
  init_worktree();
28647
28852
  init_paths();
28648
28853
 
28649
28854
  // src/board/board-pins.ts
28650
28855
  var import_node_crypto15 = require("crypto");
28651
- var import_node_fs60 = require("fs");
28652
- var import_node_path56 = require("path");
28856
+ var import_node_fs61 = require("fs");
28857
+ var import_node_path57 = require("path");
28653
28858
  init_paths();
28654
28859
  init_home_board();
28655
28860
  var FILE = "home-board-pins.json";
28656
28861
  var VERSION = 1;
28657
28862
  function pinsFile() {
28658
- return (0, import_node_path56.join)(appDataDir(), FILE);
28863
+ return (0, import_node_path57.join)(appDataDir(), FILE);
28659
28864
  }
28660
28865
  function readDisk() {
28661
28866
  const path = pinsFile();
28662
- if (!(0, import_node_fs60.existsSync)(path)) return [];
28867
+ if (!(0, import_node_fs61.existsSync)(path)) return [];
28663
28868
  try {
28664
- const raw = JSON.parse((0, import_node_fs60.readFileSync)(path, "utf8"));
28869
+ const raw = JSON.parse((0, import_node_fs61.readFileSync)(path, "utf8"));
28665
28870
  if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
28666
28871
  return raw.items.filter((item) => item?.id && item.kind && item.ref);
28667
28872
  } catch {
@@ -28669,8 +28874,8 @@ function readDisk() {
28669
28874
  }
28670
28875
  }
28671
28876
  function writeDisk(items) {
28672
- (0, import_node_fs60.mkdirSync)(appDataDir(), { recursive: true });
28673
- (0, import_node_fs60.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
28877
+ (0, import_node_fs61.mkdirSync)(appDataDir(), { recursive: true });
28878
+ (0, import_node_fs61.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
28674
28879
  }
28675
28880
  function listBoardPins() {
28676
28881
  return readDisk();
@@ -28691,7 +28896,7 @@ function homeBoardWorkspaceKey(workspaces) {
28691
28896
  return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
28692
28897
  }
28693
28898
  function cacheFile() {
28694
- return (0, import_node_path57.join)(appDataDir(), "home-board-cache.json");
28899
+ return (0, import_node_path58.join)(appDataDir(), "home-board-cache.json");
28695
28900
  }
28696
28901
  function emptyInputs() {
28697
28902
  return {
@@ -28717,9 +28922,9 @@ function shouldCacheHomeBoardInputs(inputs) {
28717
28922
  }
28718
28923
  function readDiskCache() {
28719
28924
  const path = cacheFile();
28720
- if (!(0, import_node_fs61.existsSync)(path)) return null;
28925
+ if (!(0, import_node_fs62.existsSync)(path)) return null;
28721
28926
  try {
28722
- const raw = JSON.parse((0, import_node_fs61.readFileSync)(path, "utf8"));
28927
+ const raw = JSON.parse((0, import_node_fs62.readFileSync)(path, "utf8"));
28723
28928
  if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
28724
28929
  return null;
28725
28930
  }
@@ -28733,8 +28938,8 @@ function readDiskCache() {
28733
28938
  }
28734
28939
  function writeDiskCache(entry) {
28735
28940
  try {
28736
- (0, import_node_fs61.mkdirSync)(appDataDir(), { recursive: true });
28737
- (0, import_node_fs61.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
28941
+ (0, import_node_fs62.mkdirSync)(appDataDir(), { recursive: true });
28942
+ (0, import_node_fs62.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
28738
28943
  } catch {
28739
28944
  }
28740
28945
  }
@@ -28958,14 +29163,14 @@ function orchCreateThreadAgentNote(input) {
28958
29163
  var MAX_ORCH_THREADS = 5;
28959
29164
  var CREATE_THREAD_TIMEOUT_MS = 9e4;
28960
29165
  function withTimeout2(promise, ms, label) {
28961
- return new Promise((resolve, reject) => {
29166
+ return new Promise((resolve2, reject) => {
28962
29167
  const timer = setTimeout(() => {
28963
29168
  reject(new Error(`${label} timed out after ${Math.round(ms / 1e3)}s`));
28964
29169
  }, ms);
28965
29170
  promise.then(
28966
29171
  (value) => {
28967
29172
  clearTimeout(timer);
28968
- resolve(value);
29173
+ resolve2(value);
28969
29174
  },
28970
29175
  (err) => {
28971
29176
  clearTimeout(timer);
@@ -29137,7 +29342,7 @@ async function startMcpServer() {
29137
29342
  async () => {
29138
29343
  const threads = orch.getThreads(true);
29139
29344
  const lines = threads.map((t) => {
29140
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path58.basename)(t.repoPath) || t.repoPath;
29345
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path59.basename)(t.repoPath) || t.repoPath;
29141
29346
  const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
29142
29347
  const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
29143
29348
  const preview = lastMessagePreview(t.messages, 80);