@sideboard-ai/core 0.1.85 → 0.1.87

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist/agents/cursor-runner.cjs +77 -29
  2. package/dist/agents/cursor-runner.js +55 -17
  3. package/dist/{agents-YAYNNJWC.js → agents-V6PVSQYH.js} +8 -8
  4. package/dist/{agents-FD77JUOP.js → agents-W5446HSV.js} +8 -8
  5. package/dist/{app-settings-PEXK5VEX.js → app-settings-F36ISTCF.js} +2 -2
  6. package/dist/{app-settings-K6RFCRF6.js → app-settings-HFINR3XG.js} +2 -2
  7. package/dist/{caffeinate-hold-EAZNWJBE.js → caffeinate-hold-I7SG6UQR.js} +2 -2
  8. package/dist/{caffeinate-hold-OHAUWOA6.js → caffeinate-hold-U3QJBV67.js} +2 -2
  9. package/dist/{chunk-XVFV56JG.js → chunk-3MA6JH6G.js} +5 -5
  10. package/dist/{chunk-FWJYLBO6.js → chunk-3WA37BRI.js} +1 -1
  11. package/dist/{chunk-JTHWVYSD.js → chunk-4PTN2LED.js} +5 -5
  12. package/dist/{chunk-RV6DBEDQ.js → chunk-7KDBDMNC.js} +1 -1
  13. package/dist/{chunk-SH75CXJR.js → chunk-A7LONVNO.js} +5 -5
  14. package/dist/{chunk-M37RITA6.js → chunk-B4R2VB2A.js} +164 -30
  15. package/dist/{chunk-6WQAYBVE.js → chunk-CY45C3GA.js} +4 -4
  16. package/dist/{chunk-6K5VAPVR.js → chunk-DKHGWYWR.js} +1 -1
  17. package/dist/{chunk-2N5DVTGH.js → chunk-HBXQQ5TO.js} +3 -3
  18. package/dist/{chunk-7MV3RXSC.js → chunk-JL4SJ6V7.js} +137 -26
  19. package/dist/{chunk-7FD7COKE.js → chunk-JOF3XIEM.js} +1 -1
  20. package/dist/{chunk-KRAUS3RF.js → chunk-L63LLCTX.js} +4 -4
  21. package/dist/{chunk-MFF2RE3I.js → chunk-NZPGMNFC.js} +1 -1
  22. package/dist/{chunk-HHTHF5BQ.js → chunk-QSLE4VEM.js} +4 -4
  23. package/dist/{chunk-3CCRD6WS.js → chunk-QWNROSRB.js} +6 -6
  24. package/dist/{chunk-JFQ2M6NQ.js → chunk-R2EOZNQI.js} +3 -3
  25. package/dist/{chunk-AY53MPDE.js → chunk-TC2KY5G7.js} +1 -1
  26. package/dist/{chunk-WGI6KXKJ.js → chunk-U4GZKLIV.js} +6 -6
  27. package/dist/{chunk-6GKDYUTJ.js → chunk-UVNXLTFB.js} +5 -5
  28. package/dist/{chunk-I3FRXL7J.js → chunk-XY6XXMAK.js} +1 -1
  29. package/dist/{connected-teams-BNBM7OIC.js → connected-teams-SWHJWK2A.js} +2 -2
  30. package/dist/{connected-teams-LSQ5TAZP.js → connected-teams-TLVKZPJP.js} +2 -2
  31. package/dist/{coordinator-prompt-VN7FF76K.js → coordinator-prompt-EC3KQLN3.js} +5 -5
  32. package/dist/{coordinator-prompt-YYQSPLIP.js → coordinator-prompt-PYRAXZN3.js} +5 -5
  33. package/dist/{cursor-recover-L5PNQUDT.js → cursor-recover-G34BYKL2.js} +1 -1
  34. package/dist/{cursor-recover-NNK7JPQM.js → cursor-recover-S5ORPW34.js} +1 -1
  35. package/dist/{global-workspace-BRIDCBMY.js → global-workspace-ICWOWUW6.js} +6 -6
  36. package/dist/{global-workspace-U3XVTQLL.js → global-workspace-T5IAJF4R.js} +6 -6
  37. package/dist/index.cjs +633 -526
  38. package/dist/index.d.cts +45 -11
  39. package/dist/index.d.ts +45 -11
  40. package/dist/index.js +212 -252
  41. package/dist/mcp/run-stdio.cjs +570 -490
  42. package/dist/mcp/run-stdio.js +184 -225
  43. package/dist/{paths-VPH3ITBK.js → paths-JQM2XRAD.js} +1 -1
  44. package/dist/{paths-2OFB7UJG.js → paths-TZX4L5X7.js} +1 -1
  45. package/dist/{thread-store-BUBR24YA.js → thread-store-V7NOOXKE.js} +2 -2
  46. package/dist/{thread-store-XTPFCJAI.js → thread-store-XAKWCV2E.js} +2 -2
  47. package/dist/{workspaces-IWQIWAMQ.js → workspaces-AJCAFW64.js} +7 -7
  48. package/dist/{workspaces-AIZDG6PS.js → workspaces-J4ULXOUH.js} +7 -7
  49. package/dist/{worktree-6ZALJUWG.js → worktree-4Z2VSHAQ.js} +4 -4
  50. package/dist/{worktree-7Y22WHR7.js → worktree-H57CCHWO.js} +4 -4
  51. package/package.json +1 -1
@@ -17,14 +17,14 @@ import {
17
17
  resolveQuotaFallbackAgent,
18
18
  sideboardMcpProfile,
19
19
  summarizeTurnStderr
20
- } from "../chunk-3CCRD6WS.js";
21
- import "../chunk-6K5VAPVR.js";
20
+ } from "../chunk-QWNROSRB.js";
21
+ import "../chunk-DKHGWYWR.js";
22
22
  import {
23
23
  addWorkspace,
24
24
  ensureWorkspace,
25
25
  removeWorkspace,
26
26
  syncWorkspacesFromThreads
27
- } from "../chunk-JFQ2M6NQ.js";
27
+ } from "../chunk-R2EOZNQI.js";
28
28
  import {
29
29
  extractPresentedPlan,
30
30
  readPlanFile,
@@ -32,7 +32,7 @@ import {
32
32
  } from "../chunk-N5PM7HGQ.js";
33
33
  import {
34
34
  releaseCaffeinateHoldForThread
35
- } from "../chunk-RV6DBEDQ.js";
35
+ } from "../chunk-7KDBDMNC.js";
36
36
  import {
37
37
  GLOBAL_WORKSPACE_ID,
38
38
  assertOrchestratorCapableAgent,
@@ -42,14 +42,14 @@ import {
42
42
  isGlobalThread,
43
43
  isOrchestratorThread,
44
44
  orchestratorSessionPoisonedByBuiltins
45
- } from "../chunk-6GKDYUTJ.js";
45
+ } from "../chunk-UVNXLTFB.js";
46
46
  import {
47
47
  SLACK_REPLY_FORMATTING,
48
48
  coordinatorSystemPrompt,
49
49
  coordinatorTurnReminder,
50
50
  enrichWorkspacesWithGithub,
51
51
  ensureGlobalCoordinatorCwd
52
- } from "../chunk-XVFV56JG.js";
52
+ } from "../chunk-3MA6JH6G.js";
53
53
  import {
54
54
  addPrStackLayer,
55
55
  allocateTeamName,
@@ -89,7 +89,7 @@ import {
89
89
  takenSlugsFromThread,
90
90
  threadDisplayLabel,
91
91
  worktreeNameFromPath
92
- } from "../chunk-6WQAYBVE.js";
92
+ } from "../chunk-CY45C3GA.js";
93
93
  import {
94
94
  ATTACHMENTS_DIR,
95
95
  LEGACY_ATTACHMENTS_DIR,
@@ -106,7 +106,7 @@ import {
106
106
  updateThread,
107
107
  withThreadLock,
108
108
  writeThread
109
- } from "../chunk-7FD7COKE.js";
109
+ } from "../chunk-JOF3XIEM.js";
110
110
  import {
111
111
  childEnvWithAppSettings,
112
112
  disconnectLinearConnection,
@@ -124,20 +124,22 @@ import {
124
124
  stripNestedElectronEnv,
125
125
  updateAdvancedSettings,
126
126
  writeSecureJson
127
- } from "../chunk-AY53MPDE.js";
127
+ } from "../chunk-TC2KY5G7.js";
128
128
  import {
129
129
  writePrivateFile
130
130
  } from "../chunk-NSTQ6QKD.js";
131
131
  import "../chunk-KGZBYWZ3.js";
132
132
  import {
133
133
  appDataDir,
134
+ findConventionSetup,
134
135
  loadRepoSettings,
135
136
  loadWorkspaceSettings,
137
+ runCursorWorktreeSetup,
136
138
  sideboardReposDir,
137
139
  sideboardWorkspacesDir,
138
140
  workspaceSettingsSourceLabel,
139
141
  worktreesRoot
140
- } from "../chunk-7MV3RXSC.js";
142
+ } from "../chunk-JL4SJ6V7.js";
141
143
  import {
142
144
  enrichPathWithNpmGlobalBin,
143
145
  ensureAgentPath,
@@ -652,7 +654,7 @@ async function refreshSlackReplyBadges(opts) {
652
654
  }
653
655
 
654
656
  // src/orchestrator/orchestrator.ts
655
- import { existsSync as existsSync15 } from "fs";
657
+ import { existsSync as existsSync14 } from "fs";
656
658
 
657
659
  // src/agents/spawn.ts
658
660
  import { createInterface } from "readline";
@@ -894,9 +896,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
894
896
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
895
897
  );
896
898
  }
897
- const { isGlobalThread: isGlobalThread2 } = await import("../global-workspace-U3XVTQLL.js");
899
+ const { isGlobalThread: isGlobalThread2 } = await import("../global-workspace-T5IAJF4R.js");
898
900
  if (isGlobalThread2(thread)) {
899
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("../coordinator-prompt-YYQSPLIP.js");
901
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("../coordinator-prompt-PYRAXZN3.js");
900
902
  ensureGlobalCoordinatorCwd2(
901
903
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
902
904
  );
@@ -1326,6 +1328,14 @@ async function spawnWorkspaceScript(command, opts) {
1326
1328
  child
1327
1329
  };
1328
1330
  }
1331
+ async function attachAbort(handle, signal) {
1332
+ if (signal) {
1333
+ const onAbort = () => handle.kill();
1334
+ if (signal.aborted) onAbort();
1335
+ else signal.addEventListener("abort", onAbort, { once: true });
1336
+ }
1337
+ return handle.done;
1338
+ }
1329
1339
  async function runSetupScript(repoPath, worktreePath, onLine, opts) {
1330
1340
  const settings = loadWorkspaceSettings(worktreePath, repoPath);
1331
1341
  if (!settings?.setup) return { ran: false, exitCode: null, source: null };
@@ -1335,12 +1345,7 @@ async function runSetupScript(repoPath, worktreePath, onLine, opts) {
1335
1345
  defaultBranch: opts?.defaultBranch,
1336
1346
  onLine
1337
1347
  });
1338
- if (opts?.signal) {
1339
- const onAbort = () => handle.kill();
1340
- if (opts.signal.aborted) onAbort();
1341
- else opts.signal.addEventListener("abort", onAbort, { once: true });
1342
- }
1343
- const exitCode = await handle.done;
1348
+ const exitCode = await attachAbort(handle, opts?.signal);
1344
1349
  return {
1345
1350
  ran: true,
1346
1351
  exitCode,
@@ -1348,6 +1353,34 @@ async function runSetupScript(repoPath, worktreePath, onLine, opts) {
1348
1353
  kill: handle.kill
1349
1354
  };
1350
1355
  }
1356
+ async function runConventionSetup(repoPath, worktreePath, onLine, opts) {
1357
+ const found = findConventionSetup(worktreePath, repoPath);
1358
+ if (!found) return { ran: false, exitCode: null, source: null };
1359
+ onLine?.(`[setup] ${found.source}`);
1360
+ const handle = await spawnWorkspaceScript(found.command, {
1361
+ worktreePath,
1362
+ repoPath,
1363
+ defaultBranch: opts?.defaultBranch,
1364
+ onLine
1365
+ });
1366
+ const exitCode = await attachAbort(handle, opts?.signal);
1367
+ return {
1368
+ ran: true,
1369
+ exitCode,
1370
+ source: found.source,
1371
+ kill: handle.kill
1372
+ };
1373
+ }
1374
+ async function runWorkspaceSetup(repoPath, worktreePath, onLine, opts) {
1375
+ let setup = await runSetupScript(repoPath, worktreePath, onLine, opts);
1376
+ if (!setup.ran) {
1377
+ setup = await runCursorWorktreeSetup(repoPath, worktreePath, onLine);
1378
+ }
1379
+ if (!setup.ran) {
1380
+ setup = await runConventionSetup(repoPath, worktreePath, onLine, opts);
1381
+ }
1382
+ return setup;
1383
+ }
1351
1384
  async function runArchiveScript(repoPath, worktreePath, onLine) {
1352
1385
  const settings = loadWorkspaceSettings(worktreePath, repoPath);
1353
1386
  if (!settings?.archive) return { ran: false, exitCode: null };
@@ -1440,75 +1473,9 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
1440
1473
  };
1441
1474
  }
1442
1475
 
1443
- // src/hook/cursor-worktrees.ts
1444
- import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
1445
- import { join as join5 } from "path";
1446
- import { execa as execa3 } from "execa";
1447
- import { createInterface as createInterface3 } from "readline";
1448
- function loadCursorWorktreesJson(rootPath) {
1449
- const path = join5(rootPath, ".cursor", "worktrees.json");
1450
- if (!existsSync4(path)) return null;
1451
- try {
1452
- return JSON.parse(readFileSync4(path, "utf8"));
1453
- } catch {
1454
- return null;
1455
- }
1456
- }
1457
- function resolveSetupSpec(config) {
1458
- if (process.platform === "win32") {
1459
- return config["setup-worktree-windows"] ?? config["setup-worktree"] ?? null;
1460
- }
1461
- return config["setup-worktree-unix"] ?? config["setup-worktree"] ?? null;
1462
- }
1463
- async function runCursorWorktreeSetup(repoPath, worktreePath, onLine) {
1464
- const fromWorktree = loadCursorWorktreesJson(worktreePath);
1465
- const fromRepo = worktreePath !== repoPath ? loadCursorWorktreesJson(repoPath) : null;
1466
- const config = fromWorktree ?? fromRepo;
1467
- if (!config) return { ran: false, exitCode: null, source: null };
1468
- const spec = resolveSetupSpec(config);
1469
- if (!spec) return { ran: false, exitCode: null, source: null };
1470
- const sourceLabel = fromWorktree ? ".cursor/worktrees.json (worktree)" : ".cursor/worktrees.json (main repo)";
1471
- const env = {
1472
- ...process.env,
1473
- ROOT_WORKTREE_PATH: repoPath
1474
- };
1475
- if (process.platform === "win32") {
1476
- env.ROOT_WORKTREE_PATH = repoPath;
1477
- }
1478
- const commands = Array.isArray(spec) ? spec : [spec.endsWith(".sh") || spec.endsWith(".ps1") ? join5(
1479
- fromWorktree ? worktreePath : repoPath,
1480
- ".cursor",
1481
- spec
1482
- ) : spec];
1483
- let lastExit = 0;
1484
- for (const command of commands) {
1485
- const isScriptPath = typeof spec === "string" && (spec.endsWith(".sh") || spec.endsWith(".ps1"));
1486
- const shell = process.platform === "win32" ? "powershell" : "bash";
1487
- const args = process.platform === "win32" ? isScriptPath ? ["-File", command] : ["-Command", command] : isScriptPath ? [command] : ["-lc", command];
1488
- onLine?.(`[cursor setup] ${command}`);
1489
- const child = execa3(shell, args, {
1490
- cwd: worktreePath,
1491
- reject: false,
1492
- env
1493
- });
1494
- if (child.stdout && onLine) {
1495
- const rl = createInterface3({ input: child.stdout });
1496
- rl.on("line", onLine);
1497
- }
1498
- if (child.stderr && onLine) {
1499
- const rl = createInterface3({ input: child.stderr });
1500
- rl.on("line", onLine);
1501
- }
1502
- const result = await child;
1503
- lastExit = result.exitCode ?? null;
1504
- if (lastExit !== 0 && lastExit !== null) break;
1505
- }
1506
- return { ran: true, exitCode: lastExit, source: sourceLabel };
1507
- }
1508
-
1509
1476
  // src/git/orphan-cleanup.ts
1510
- import { existsSync as existsSync5, readdirSync as readdirSync2, statSync } from "fs";
1511
- import { join as join6 } from "path";
1477
+ import { existsSync as existsSync4, readdirSync as readdirSync2, statSync } from "fs";
1478
+ import { join as join5 } from "path";
1512
1479
  function isSideboardWorktreePath(path) {
1513
1480
  return path.includes("/.sideboard/worktrees/") || path.includes("/sideboard/workspaces/");
1514
1481
  }
@@ -1519,7 +1486,7 @@ async function findOrphanWorktrees(repoPaths) {
1519
1486
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
1520
1487
  );
1521
1488
  const homeRoot = sideboardWorkspacesDir();
1522
- if (existsSync5(homeRoot)) {
1489
+ if (existsSync4(homeRoot)) {
1523
1490
  try {
1524
1491
  for (const entry of readdirSync2(homeRoot, { withFileTypes: true })) {
1525
1492
  if (!entry.isDirectory()) continue;
@@ -1531,7 +1498,7 @@ async function findOrphanWorktrees(repoPaths) {
1531
1498
  const orphans = [];
1532
1499
  const seen = /* @__PURE__ */ new Set();
1533
1500
  for (const repoPath of repos) {
1534
- if (!repoPath || !existsSync5(repoPath)) continue;
1501
+ if (!repoPath || !existsSync4(repoPath)) continue;
1535
1502
  try {
1536
1503
  const wts = await listWorktrees(repoPath);
1537
1504
  for (const wt of wts) {
@@ -1552,12 +1519,12 @@ async function findOrphanWorktrees(repoPaths) {
1552
1519
  }
1553
1520
  try {
1554
1521
  const root = worktreesRoot(repoPath);
1555
- if (existsSync5(root)) {
1522
+ if (existsSync4(root)) {
1556
1523
  for (const entry of readdirSync2(root, { withFileTypes: true })) {
1557
1524
  if (!entry.isDirectory()) continue;
1558
- const path = join6(root, entry.name).replace(/\/$/, "");
1525
+ const path = join5(root, entry.name).replace(/\/$/, "");
1559
1526
  if (known.has(path) || seen.has(path)) continue;
1560
- if (!existsSync5(join6(path, ".git"))) continue;
1527
+ if (!existsSync4(join5(path, ".git"))) continue;
1561
1528
  seen.add(path);
1562
1529
  let mtimeMs = 0;
1563
1530
  try {
@@ -1615,11 +1582,11 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
1615
1582
  }
1616
1583
 
1617
1584
  // src/git/apply-into-main.ts
1618
- import { execa as execa4 } from "execa";
1585
+ import { execa as execa3 } from "execa";
1619
1586
  async function applyThreadIntoMain(thread, opts) {
1620
1587
  const method = opts?.method ?? "merge";
1621
1588
  const target = opts?.targetBranch?.trim() || await resolveDefaultBranch(thread.repoPath);
1622
- const status = await execa4("git", ["status", "--porcelain"], {
1589
+ const status = await execa3("git", ["status", "--porcelain"], {
1623
1590
  cwd: thread.repoPath,
1624
1591
  reject: false
1625
1592
  });
@@ -1628,7 +1595,7 @@ async function applyThreadIntoMain(thread, opts) {
1628
1595
  `Main checkout is dirty \u2014 commit or stash before apply-into-main (${thread.repoPath})`
1629
1596
  );
1630
1597
  }
1631
- const checkout = await execa4("git", ["checkout", target], {
1598
+ const checkout = await execa3("git", ["checkout", target], {
1632
1599
  cwd: thread.repoPath,
1633
1600
  reject: false
1634
1601
  });
@@ -1638,7 +1605,7 @@ async function applyThreadIntoMain(thread, opts) {
1638
1605
  );
1639
1606
  }
1640
1607
  if (method === "cherry-pick") {
1641
- const log = await execa4(
1608
+ const log = await execa3(
1642
1609
  "git",
1643
1610
  ["log", "--reverse", "--format=%H", `${target}..${thread.branchName}`],
1644
1611
  { cwd: thread.repoPath, reject: false }
@@ -1653,12 +1620,12 @@ async function applyThreadIntoMain(thread, opts) {
1653
1620
  };
1654
1621
  }
1655
1622
  for (const sha of shas) {
1656
- const cp = await execa4("git", ["cherry-pick", sha], {
1623
+ const cp = await execa3("git", ["cherry-pick", sha], {
1657
1624
  cwd: thread.repoPath,
1658
1625
  reject: false
1659
1626
  });
1660
1627
  if (cp.exitCode !== 0) {
1661
- await execa4("git", ["cherry-pick", "--abort"], {
1628
+ await execa3("git", ["cherry-pick", "--abort"], {
1662
1629
  cwd: thread.repoPath,
1663
1630
  reject: false
1664
1631
  });
@@ -1674,13 +1641,13 @@ async function applyThreadIntoMain(thread, opts) {
1674
1641
  message: `Cherry-picked ${shas.length} commit(s) from ${thread.branchName} into ${target}`
1675
1642
  };
1676
1643
  }
1677
- const merge = await execa4(
1644
+ const merge = await execa3(
1678
1645
  "git",
1679
1646
  ["merge", "--no-ff", "-m", `Apply Sideboard thread ${thread.branchName}`, thread.branchName],
1680
1647
  { cwd: thread.repoPath, reject: false }
1681
1648
  );
1682
1649
  if (merge.exitCode !== 0) {
1683
- await execa4("git", ["merge", "--abort"], {
1650
+ await execa3("git", ["merge", "--abort"], {
1684
1651
  cwd: thread.repoPath,
1685
1652
  reject: false
1686
1653
  });
@@ -1697,9 +1664,9 @@ async function applyThreadIntoMain(thread, opts) {
1697
1664
  }
1698
1665
 
1699
1666
  // src/git/clone-repo.ts
1700
- import { existsSync as existsSync6 } from "fs";
1701
- import { basename as basename2, join as join7 } from "path";
1702
- import { execa as execa5 } from "execa";
1667
+ import { existsSync as existsSync5 } from "fs";
1668
+ import { basename as basename2, join as join6 } from "path";
1669
+ import { execa as execa4 } from "execa";
1703
1670
  async function cloneRepoIntoSideboard(opts) {
1704
1671
  const url = opts.url.trim();
1705
1672
  if (!url) throw new Error("Clone URL is required");
@@ -1709,13 +1676,13 @@ async function cloneRepoIntoSideboard(opts) {
1709
1676
  name = leaf || "repo";
1710
1677
  }
1711
1678
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
1712
- const dest = join7(sideboardReposDir(), name);
1713
- if (existsSync6(dest)) {
1679
+ const dest = join6(sideboardReposDir(), name);
1680
+ if (existsSync5(dest)) {
1714
1681
  const repoPath2 = await resolveRepoRoot(dest);
1715
1682
  const workspace2 = await ensureWorkspace(repoPath2);
1716
1683
  return { repoPath: repoPath2, workspace: workspace2 };
1717
1684
  }
1718
- const result = await execa5("git", ["clone", url, dest], { reject: false });
1685
+ const result = await execa4("git", ["clone", url, dest], { reject: false });
1719
1686
  if (result.exitCode !== 0) {
1720
1687
  throw new Error(
1721
1688
  `git clone failed: ${result.stderr?.trim() || result.stdout?.trim() || `exit ${result.exitCode}`}`
@@ -1727,7 +1694,7 @@ async function cloneRepoIntoSideboard(opts) {
1727
1694
  }
1728
1695
 
1729
1696
  // src/threads/create.ts
1730
- import { existsSync as existsSync7 } from "fs";
1697
+ import { existsSync as existsSync6 } from "fs";
1731
1698
 
1732
1699
  // src/detect/detect.ts
1733
1700
  var REQUIRE_AGENT_TIMEOUT_MS = 8e3;
@@ -1767,7 +1734,7 @@ async function createThread(input, _onSetupLine) {
1767
1734
  });
1768
1735
  await requireAgent(resolved.agent);
1769
1736
  const repoPath = await resolveRepoRoot(input.repoPath);
1770
- if (!existsSync7(repoPath)) {
1737
+ if (!existsSync6(repoPath)) {
1771
1738
  throw new Error(`Repo not found: ${repoPath}`);
1772
1739
  }
1773
1740
  let sourceRef = input.sourceRef;
@@ -1825,7 +1792,7 @@ async function createThread(input, _onSetupLine) {
1825
1792
  return readThread(thread.id) ?? thread;
1826
1793
  }
1827
1794
  async function listLinearIssues(agent, repoPath) {
1828
- const { getAdapter: getAdapter2 } = await import("../agents-FD77JUOP.js");
1795
+ const { getAdapter: getAdapter2 } = await import("../agents-W5446HSV.js");
1829
1796
  await requireAgent(agent, { requireLinear: true });
1830
1797
  const adapter = getAdapter2(agent);
1831
1798
  if (!adapter.listLinearIssues) {
@@ -2219,8 +2186,8 @@ function forkChatTab(input) {
2219
2186
 
2220
2187
  // src/review/request-review.ts
2221
2188
  import { randomUUID as randomUUID2 } from "crypto";
2222
- import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync } from "fs";
2223
- import { dirname as dirname2, join as join8 } from "path";
2189
+ import { existsSync as existsSync7, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync } from "fs";
2190
+ import { dirname as dirname2, join as join7 } from "path";
2224
2191
 
2225
2192
  // src/review/review-request-template.ts
2226
2193
  var REVIEW_REQUEST_TEMPLATE = `# Review guidelines:
@@ -2365,22 +2332,22 @@ function shouldRefreshReviewRequestTemplate(content) {
2365
2332
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
2366
2333
  }
2367
2334
  function readTextIfPresent(abs) {
2368
- if (!existsSync8(abs)) return null;
2335
+ if (!existsSync7(abs)) return null;
2369
2336
  try {
2370
- const content = readFileSync5(abs, "utf8");
2337
+ const content = readFileSync4(abs, "utf8");
2371
2338
  return content.trim() ? content : null;
2372
2339
  } catch {
2373
2340
  return null;
2374
2341
  }
2375
2342
  }
2376
2343
  function ensureAttachmentsGitignore(worktreePath) {
2377
- const gitignoreAbs = join8(worktreePath, ATTACHMENTS_DIR, ".gitignore");
2378
- if (existsSync8(gitignoreAbs)) return;
2344
+ const gitignoreAbs = join7(worktreePath, ATTACHMENTS_DIR, ".gitignore");
2345
+ if (existsSync7(gitignoreAbs)) return;
2379
2346
  mkdirSync2(dirname2(gitignoreAbs), { recursive: true });
2380
2347
  writeFileSync(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
2381
2348
  }
2382
2349
  function resolveReviewGuidelines(worktreePath) {
2383
- const repoAbs = join8(worktreePath, REPO_REVIEW_PATH);
2350
+ const repoAbs = join7(worktreePath, REPO_REVIEW_PATH);
2384
2351
  const repoContent = readTextIfPresent(repoAbs);
2385
2352
  if (repoContent) {
2386
2353
  return {
@@ -2390,7 +2357,7 @@ function resolveReviewGuidelines(worktreePath) {
2390
2357
  source: "repo"
2391
2358
  };
2392
2359
  }
2393
- const localAbs = join8(worktreePath, REVIEW_REQUEST_PATH);
2360
+ const localAbs = join7(worktreePath, REVIEW_REQUEST_PATH);
2394
2361
  const localContent = readTextIfPresent(localAbs);
2395
2362
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
2396
2363
  return {
@@ -2400,7 +2367,7 @@ function resolveReviewGuidelines(worktreePath) {
2400
2367
  source: "local"
2401
2368
  };
2402
2369
  }
2403
- const legacyAbs = join8(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
2370
+ const legacyAbs = join7(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
2404
2371
  const legacyContent = readTextIfPresent(legacyAbs);
2405
2372
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
2406
2373
  return {
@@ -2608,23 +2575,23 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
2608
2575
  import { execFileSync } from "child_process";
2609
2576
  import {
2610
2577
  copyFileSync as copyFileSync2,
2611
- existsSync as existsSync9,
2578
+ existsSync as existsSync8,
2612
2579
  mkdtempSync,
2613
2580
  readdirSync as readdirSync3,
2614
- readFileSync as readFileSync6,
2581
+ readFileSync as readFileSync5,
2615
2582
  rmSync
2616
2583
  } from "fs";
2617
2584
  import { tmpdir } from "os";
2618
- import { join as join9 } from "path";
2585
+ import { join as join8 } from "path";
2619
2586
  import Database from "better-sqlite3";
2620
- var CONDUCTOR_APP_SUPPORT = join9(
2587
+ var CONDUCTOR_APP_SUPPORT = join8(
2621
2588
  process.env.HOME ?? "",
2622
2589
  "Library",
2623
2590
  "Application Support",
2624
2591
  "com.conductor.app"
2625
2592
  );
2626
- var CONDUCTOR_DB = join9(CONDUCTOR_APP_SUPPORT, "conductor.db");
2627
- var CURSOR_SDK_STORE = join9(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
2593
+ var CONDUCTOR_DB = join8(CONDUCTOR_APP_SUPPORT, "conductor.db");
2594
+ var CURSOR_SDK_STORE = join8(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
2628
2595
  function mapAgentType(raw) {
2629
2596
  if (!raw) return null;
2630
2597
  const v = raw.toLowerCase();
@@ -2636,7 +2603,7 @@ function mapAgentType(raw) {
2636
2603
  return null;
2637
2604
  }
2638
2605
  function resolveConductorCursorAgentId(workspacePath) {
2639
- if (!workspacePath || !existsSync9(CURSOR_SDK_STORE)) return null;
2606
+ if (!workspacePath || !existsSync8(CURSOR_SDK_STORE)) return null;
2640
2607
  const normalized = workspacePath.replace(/\/$/, "");
2641
2608
  let best = null;
2642
2609
  let hashes;
@@ -2646,11 +2613,11 @@ function resolveConductorCursorAgentId(workspacePath) {
2646
2613
  return null;
2647
2614
  }
2648
2615
  for (const hash of hashes) {
2649
- const agentsFile = join9(CURSOR_SDK_STORE, hash, "agents.ndjson");
2650
- if (!existsSync9(agentsFile)) continue;
2616
+ const agentsFile = join8(CURSOR_SDK_STORE, hash, "agents.ndjson");
2617
+ if (!existsSync8(agentsFile)) continue;
2651
2618
  let text3;
2652
2619
  try {
2653
- text3 = readFileSync6(agentsFile, "utf8");
2620
+ text3 = readFileSync5(agentsFile, "utf8");
2654
2621
  } catch {
2655
2622
  continue;
2656
2623
  }
@@ -2674,7 +2641,7 @@ function resolveConductorCursorAgentId(workspacePath) {
2674
2641
  return best?.agentId ?? null;
2675
2642
  }
2676
2643
  async function adoptThread(input) {
2677
- if (!existsSync9(input.worktreePath)) {
2644
+ if (!existsSync8(input.worktreePath)) {
2678
2645
  throw new Error(`Worktree not found: ${input.worktreePath}`);
2679
2646
  }
2680
2647
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -2693,21 +2660,21 @@ async function adoptThread(input) {
2693
2660
  messages: input.messages ?? []
2694
2661
  });
2695
2662
  writeThread(thread);
2696
- const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-AIZDG6PS.js");
2663
+ const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-J4ULXOUH.js");
2697
2664
  await ensureWorkspace2(repoPath);
2698
2665
  return thread;
2699
2666
  }
2700
2667
  function listConductorWorkspaces() {
2701
- if (!existsSync9(CONDUCTOR_DB)) {
2668
+ if (!existsSync8(CONDUCTOR_DB)) {
2702
2669
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
2703
2670
  }
2704
- const tmp = mkdtempSync(join9(tmpdir(), "sideboard-conductor-"));
2705
- const snapshot = join9(tmp, "conductor.db");
2671
+ const tmp = mkdtempSync(join8(tmpdir(), "sideboard-conductor-"));
2672
+ const snapshot = join8(tmp, "conductor.db");
2706
2673
  try {
2707
2674
  copyFileSync2(CONDUCTOR_DB, snapshot);
2708
2675
  for (const suffix of ["-wal", "-shm"]) {
2709
2676
  const src = `${CONDUCTOR_DB}${suffix}`;
2710
- if (existsSync9(src)) {
2677
+ if (existsSync8(src)) {
2711
2678
  try {
2712
2679
  copyFileSync2(src, `${snapshot}${suffix}`);
2713
2680
  } catch {
@@ -2789,16 +2756,16 @@ function listConductorWorkspaces() {
2789
2756
  }
2790
2757
  }
2791
2758
  function importConductorWorkspace(workspaceId) {
2792
- if (!existsSync9(CONDUCTOR_DB)) {
2759
+ if (!existsSync8(CONDUCTOR_DB)) {
2793
2760
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
2794
2761
  }
2795
- const tmp = mkdtempSync(join9(tmpdir(), "sideboard-conductor-"));
2796
- const snapshot = join9(tmp, "conductor.db");
2762
+ const tmp = mkdtempSync(join8(tmpdir(), "sideboard-conductor-"));
2763
+ const snapshot = join8(tmp, "conductor.db");
2797
2764
  try {
2798
2765
  copyFileSync2(CONDUCTOR_DB, snapshot);
2799
2766
  for (const suffix of ["-wal", "-shm"]) {
2800
2767
  const src = `${CONDUCTOR_DB}${suffix}`;
2801
- if (existsSync9(src)) {
2768
+ if (existsSync8(src)) {
2802
2769
  try {
2803
2770
  copyFileSync2(src, `${snapshot}${suffix}`);
2804
2771
  } catch {
@@ -2818,7 +2785,7 @@ function importConductorWorkspace(workspaceId) {
2818
2785
  ).get(workspaceId);
2819
2786
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
2820
2787
  const worktreePath = String(row.workspacePath);
2821
- if (!existsSync9(worktreePath)) {
2788
+ if (!existsSync8(worktreePath)) {
2822
2789
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
2823
2790
  }
2824
2791
  let sessionId = null;
@@ -2889,7 +2856,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
2889
2856
  }
2890
2857
 
2891
2858
  // src/threads/stack-layers.ts
2892
- import { existsSync as existsSync10 } from "fs";
2859
+ import { existsSync as existsSync9 } from "fs";
2893
2860
  function stackIdFrom(stack) {
2894
2861
  if (stack.stackNumber != null) return `gh-stack-${stack.stackNumber}`;
2895
2862
  const key = stack.layers.map((l) => l.branchName).join("|");
@@ -2952,7 +2919,7 @@ async function openStackLayer(input, _onSetupLine) {
2952
2919
  let createdWorktree = false;
2953
2920
  const trees = await listWorktrees(repoPath);
2954
2921
  const checkedOut = trees.find((w) => w.branch === branchName);
2955
- if (checkedOut?.path && existsSync10(checkedOut.path)) {
2922
+ if (checkedOut?.path && existsSync9(checkedOut.path)) {
2956
2923
  if (input.reuseExistingWorktree !== false) {
2957
2924
  worktreePath = checkedOut.path;
2958
2925
  } else {
@@ -3094,7 +3061,7 @@ async function initStackFromThread(input, onSetupLine) {
3094
3061
  async function createPrStack(input, onSetupLine) {
3095
3062
  await requireAgent(input.agent);
3096
3063
  const repoPath = await resolveRepoRoot(input.repoPath);
3097
- if (!existsSync10(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
3064
+ if (!existsSync9(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
3098
3065
  if (!input.branches.length) throw new Error("At least one branch name required");
3099
3066
  const status = await detectGhStack(repoPath);
3100
3067
  if (!status.available) throw new Error(status.reason);
@@ -3161,7 +3128,7 @@ async function createPrStack(input, onSetupLine) {
3161
3128
  }
3162
3129
  }
3163
3130
  const claimed = new Set(threads.map((t) => t.worktreePath));
3164
- if (!claimed.has(bootstrap.worktreePath) && existsSync10(bootstrap.worktreePath)) {
3131
+ if (!claimed.has(bootstrap.worktreePath) && existsSync9(bootstrap.worktreePath)) {
3165
3132
  try {
3166
3133
  await removeWorktree(repoPath, bootstrap.worktreePath, {
3167
3134
  deleteBranch: bootstrap.branchName
@@ -3173,10 +3140,10 @@ async function createPrStack(input, onSetupLine) {
3173
3140
  }
3174
3141
 
3175
3142
  // src/diff/diff.ts
3176
- import { existsSync as existsSync11, mkdirSync as mkdirSync3, readFileSync as readFileSync7, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
3177
- import { dirname as dirname3, join as join10 } from "path";
3143
+ import { existsSync as existsSync10, mkdirSync as mkdirSync3, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
3144
+ import { dirname as dirname3, join as join9 } from "path";
3178
3145
  async function inspectGitWorktree(worktreePath) {
3179
- if (!worktreePath || !existsSync11(worktreePath)) return "missing_worktree";
3146
+ if (!worktreePath || !existsSync10(worktreePath)) return "missing_worktree";
3180
3147
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
3181
3148
  reject: false
3182
3149
  });
@@ -3184,7 +3151,7 @@ async function inspectGitWorktree(worktreePath) {
3184
3151
  return "ok";
3185
3152
  }
3186
3153
  async function initializeGitRepository(worktreePath) {
3187
- if (!worktreePath || !existsSync11(worktreePath)) {
3154
+ if (!worktreePath || !existsSync10(worktreePath)) {
3188
3155
  throw new Error("Worktree not found");
3189
3156
  }
3190
3157
  const status = await inspectGitWorktree(worktreePath);
@@ -3319,11 +3286,11 @@ new file mode 100644
3319
3286
  };
3320
3287
  }
3321
3288
  async function untrackedPatch(worktreePath, path, maxHunk) {
3322
- const abs = join10(worktreePath, path);
3289
+ const abs = join9(worktreePath, path);
3323
3290
  try {
3324
3291
  const st = statSync2(abs);
3325
3292
  if (st.isFile() && st.size > maxHunk) {
3326
- const buf = readFileSync7(abs).subarray(0, maxHunk);
3293
+ const buf = readFileSync6(abs).subarray(0, maxHunk);
3327
3294
  return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
3328
3295
  }
3329
3296
  } catch {
@@ -3824,7 +3791,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
3824
3791
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
3825
3792
  assertSafeRelativePath(relativePath);
3826
3793
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
3827
- const abs = join10(worktreePath, relativePath);
3794
+ const abs = join9(worktreePath, relativePath);
3828
3795
  const st = statSync2(abs);
3829
3796
  if (!st.isFile()) {
3830
3797
  throw new Error(`Not a file: ${relativePath}`);
@@ -3834,7 +3801,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
3834
3801
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
3835
3802
  );
3836
3803
  }
3837
- const buf = readFileSync7(abs);
3804
+ const buf = readFileSync6(abs);
3838
3805
  return {
3839
3806
  path: relativePath,
3840
3807
  contentBase64: buf.toString("base64"),
@@ -3844,12 +3811,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
3844
3811
  function readWorktreeFile(worktreePath, relativePath, opts) {
3845
3812
  assertSafeRelativePath(relativePath);
3846
3813
  const maxBytes = opts?.maxBytes ?? 2e5;
3847
- const abs = join10(worktreePath, relativePath);
3814
+ const abs = join9(worktreePath, relativePath);
3848
3815
  const st = statSync2(abs);
3849
3816
  if (!st.isFile()) {
3850
3817
  throw new Error(`Not a file: ${relativePath}`);
3851
3818
  }
3852
- const buf = readFileSync7(abs);
3819
+ const buf = readFileSync6(abs);
3853
3820
  if (isImageRelativePath(relativePath)) {
3854
3821
  const maxImageBytes = Math.max(maxBytes, 15e6);
3855
3822
  const truncated2 = buf.length > maxImageBytes;
@@ -3892,7 +3859,7 @@ function assertSafeRelativePath(relativePath) {
3892
3859
  }
3893
3860
  function writeWorktreeFile(worktreePath, relativePath, content) {
3894
3861
  assertSafeRelativePath(relativePath);
3895
- const abs = join10(worktreePath, relativePath);
3862
+ const abs = join9(worktreePath, relativePath);
3896
3863
  mkdirSync3(dirname3(abs), { recursive: true });
3897
3864
  writeFileSync2(abs, content, "utf8");
3898
3865
  return { path: relativePath };
@@ -3997,9 +3964,9 @@ async function confirmLand(thread, opts) {
3997
3964
  }
3998
3965
 
3999
3966
  // src/skills/discover.ts
4000
- import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync8, statSync as statSync3 } from "fs";
3967
+ import { existsSync as existsSync11, readdirSync as readdirSync4, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
4001
3968
  import { homedir } from "os";
4002
- import { join as join11 } from "path";
3969
+ import { join as join10 } from "path";
4003
3970
  function toCommand(name) {
4004
3971
  return name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
4005
3972
  }
@@ -4031,7 +3998,7 @@ function parseFrontmatter(content) {
4031
3998
  }
4032
3999
  function readSkill(skillMd, source) {
4033
4000
  try {
4034
- const content = readFileSync8(skillMd, "utf8");
4001
+ const content = readFileSync7(skillMd, "utf8");
4035
4002
  const { name: fmName, description } = parseFrontmatter(content);
4036
4003
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
4037
4004
  const name = fmName || dirName;
@@ -4050,7 +4017,7 @@ function readSkill(skillMd, source) {
4050
4017
  }
4051
4018
  }
4052
4019
  function scanSkillsDir(dir, source, out) {
4053
- if (!existsSync12(dir)) return;
4020
+ if (!existsSync11(dir)) return;
4054
4021
  let entries;
4055
4022
  try {
4056
4023
  entries = readdirSync4(dir);
@@ -4059,8 +4026,8 @@ function scanSkillsDir(dir, source, out) {
4059
4026
  }
4060
4027
  for (const entry of entries) {
4061
4028
  if (entry.startsWith(".")) continue;
4062
- const skillMd = join11(dir, entry, "SKILL.md");
4063
- if (!existsSync12(skillMd)) continue;
4029
+ const skillMd = join10(dir, entry, "SKILL.md");
4030
+ if (!existsSync11(skillMd)) continue;
4064
4031
  try {
4065
4032
  if (!statSync3(skillMd).isFile()) continue;
4066
4033
  } catch {
@@ -4071,7 +4038,7 @@ function scanSkillsDir(dir, source, out) {
4071
4038
  }
4072
4039
  }
4073
4040
  function scanClaudePluginSkills(pluginsRoot, out) {
4074
- if (!existsSync12(pluginsRoot)) return;
4041
+ if (!existsSync11(pluginsRoot)) return;
4075
4042
  const walk = (dir, depth, lookingForSkillsDir) => {
4076
4043
  if (depth > 7) return;
4077
4044
  let entries;
@@ -4081,12 +4048,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
4081
4048
  return;
4082
4049
  }
4083
4050
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
4084
- const skill = readSkill(join11(dir, "SKILL.md"), "cli");
4051
+ const skill = readSkill(join10(dir, "SKILL.md"), "cli");
4085
4052
  if (skill) out.push(skill);
4086
4053
  }
4087
4054
  for (const entry of entries) {
4088
4055
  if (entry === "node_modules" || entry === ".git") continue;
4089
- const full = join11(dir, entry);
4056
+ const full = join10(dir, entry);
4090
4057
  try {
4091
4058
  if (!statSync3(full).isDirectory()) continue;
4092
4059
  } catch {
@@ -4106,17 +4073,17 @@ function discoverSkills(worktreePath) {
4106
4073
  const home = homedir();
4107
4074
  const collected = [];
4108
4075
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
4109
- scanSkillsDir(join11(worktreePath, rel), "workspace", collected);
4076
+ scanSkillsDir(join10(worktreePath, rel), "workspace", collected);
4110
4077
  }
4111
4078
  for (const abs of [
4112
- join11(home, ".claude/skills"),
4113
- join11(home, ".cursor/skills"),
4114
- join11(home, ".sideboard/skills"),
4115
- join11(home, ".brightsy/skills")
4079
+ join10(home, ".claude/skills"),
4080
+ join10(home, ".cursor/skills"),
4081
+ join10(home, ".sideboard/skills"),
4082
+ join10(home, ".brightsy/skills")
4116
4083
  ]) {
4117
4084
  scanSkillsDir(abs, "user", collected);
4118
4085
  }
4119
- scanClaudePluginSkills(join11(home, ".claude/plugins"), collected);
4086
+ scanClaudePluginSkills(join10(home, ".claude/plugins"), collected);
4120
4087
  const rank = { workspace: 0, user: 1, cli: 2 };
4121
4088
  const byCommand = /* @__PURE__ */ new Map();
4122
4089
  for (const skill of collected) {
@@ -4128,7 +4095,7 @@ function discoverSkills(worktreePath) {
4128
4095
  return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
4129
4096
  }
4130
4097
  function readSkillBody(skillPath, maxChars = 12e3) {
4131
- const raw = readFileSync8(skillPath, "utf8");
4098
+ const raw = readFileSync7(skillPath, "utf8");
4132
4099
  if (raw.startsWith("---")) {
4133
4100
  const end = raw.indexOf("\n---", 3);
4134
4101
  if (end >= 0) {
@@ -4221,8 +4188,8 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
4221
4188
  }
4222
4189
 
4223
4190
  // src/composer/stage-files.ts
4224
- import { copyFileSync as copyFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync4, readFileSync as readFileSync9, statSync as statSync4, writeFileSync as writeFileSync3 } from "fs";
4225
- import { basename as basename3, extname, join as join12 } from "path";
4191
+ import { copyFileSync as copyFileSync3, existsSync as existsSync12, mkdirSync as mkdirSync4, readFileSync as readFileSync8, statSync as statSync4, writeFileSync as writeFileSync3 } from "fs";
4192
+ import { basename as basename3, extname, join as join11 } from "path";
4226
4193
  import { randomUUID as randomUUID4 } from "crypto";
4227
4194
  var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
4228
4195
  "png",
@@ -4257,22 +4224,22 @@ function imageMimeType(filePath) {
4257
4224
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
4258
4225
  }
4259
4226
  function ensureAttachmentsDir(worktreePath) {
4260
- const dir = join12(worktreePath, ATTACHMENTS_DIR);
4227
+ const dir = join11(worktreePath, ATTACHMENTS_DIR);
4261
4228
  mkdirSync4(dir, { recursive: true });
4262
- const gi = join12(dir, ".gitignore");
4263
- if (!existsSync13(gi)) {
4229
+ const gi = join11(dir, ".gitignore");
4230
+ if (!existsSync12(gi)) {
4264
4231
  writeFileSync3(gi, attachmentsGitignoreBody(), "utf8");
4265
4232
  }
4266
4233
  return dir;
4267
4234
  }
4268
4235
  function uniqueAttachmentName(dir, originalName) {
4269
4236
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
4270
- if (!existsSync13(join12(dir, safe))) return safe;
4237
+ if (!existsSync12(join11(dir, safe))) return safe;
4271
4238
  const ext = extname(safe);
4272
4239
  const stem = ext ? safe.slice(0, -ext.length) : safe;
4273
4240
  for (let i = 1; i < 1e4; i++) {
4274
4241
  const candidate = `${stem}-${i}${ext}`;
4275
- if (!existsSync13(join12(dir, candidate))) return candidate;
4242
+ if (!existsSync12(join11(dir, candidate))) return candidate;
4276
4243
  }
4277
4244
  return `${stem}-${randomUUID4()}${ext}`;
4278
4245
  }
@@ -4333,10 +4300,10 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
4333
4300
  const st = statSync4(abs);
4334
4301
  if (!st.isFile()) continue;
4335
4302
  const name = uniqueAttachmentName(dir, originalName);
4336
- const destAbs = join12(dir, name);
4303
+ const destAbs = join11(dir, name);
4337
4304
  copyFileSync3(abs, destAbs);
4338
4305
  const rel = `${ATTACHMENTS_DIR}/${name}`;
4339
- const buf = readFileSync9(destAbs);
4306
+ const buf = readFileSync8(destAbs);
4340
4307
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
4341
4308
  } catch (err) {
4342
4309
  out.push({
@@ -4358,7 +4325,7 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
4358
4325
  try {
4359
4326
  const buf = Buffer.from(item.dataBase64, "base64");
4360
4327
  const name = uniqueAttachmentName(dir, originalName);
4361
- const destAbs = join12(dir, name);
4328
+ const destAbs = join11(dir, name);
4362
4329
  writeFileSync3(destAbs, buf);
4363
4330
  const rel = `${ATTACHMENTS_DIR}/${name}`;
4364
4331
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
@@ -4387,10 +4354,10 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
4387
4354
  }
4388
4355
  const name = basename3(rel);
4389
4356
  try {
4390
- const abs = join12(worktreePath, rel);
4357
+ const abs = join11(worktreePath, rel);
4391
4358
  const st = statSync4(abs);
4392
4359
  if (!st.isFile()) continue;
4393
- const buf = readFileSync9(abs);
4360
+ const buf = readFileSync8(abs);
4394
4361
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
4395
4362
  } catch (err) {
4396
4363
  out.push({
@@ -4405,8 +4372,8 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
4405
4372
  }
4406
4373
 
4407
4374
  // src/agents/instructions.ts
4408
- import { existsSync as existsSync14, readFileSync as readFileSync10, statSync as statSync5 } from "fs";
4409
- import { join as join13 } from "path";
4375
+ import { existsSync as existsSync13, readFileSync as readFileSync9, statSync as statSync5 } from "fs";
4376
+ import { join as join12 } from "path";
4410
4377
  function normPath(p) {
4411
4378
  return p.replace(/\/+$/, "");
4412
4379
  }
@@ -4666,7 +4633,7 @@ var Orchestrator = class {
4666
4633
  }
4667
4634
  continue;
4668
4635
  }
4669
- if (!existsSync15(thread.worktreePath)) {
4636
+ if (!existsSync14(thread.worktreePath)) {
4670
4637
  setStatus(thread.id, "broken", "Worktree missing on disk");
4671
4638
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
4672
4639
  continue;
@@ -4685,7 +4652,7 @@ var Orchestrator = class {
4685
4652
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
4686
4653
  });
4687
4654
  }
4688
- const { autoCleanupOrphansEnabled } = await import("../app-settings-PEXK5VEX.js");
4655
+ const { autoCleanupOrphansEnabled } = await import("../app-settings-F36ISTCF.js");
4689
4656
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
4690
4657
  await cleanupOrphanWorktrees({ repoPaths });
4691
4658
  }
@@ -4841,14 +4808,7 @@ var Orchestrator = class {
4841
4808
  return thread;
4842
4809
  }
4843
4810
  async finishCreateThread(threadId, prompt) {
4844
- await this.runSetupAfterCreate(threadId);
4845
- const { autoRunAfterSetupEnabled } = await import("../app-settings-PEXK5VEX.js");
4846
- if (autoRunAfterSetupEnabled()) {
4847
- try {
4848
- await this.startDev(threadId);
4849
- } catch {
4850
- }
4851
- }
4811
+ const setup = this.runSetupAfterCreate(threadId);
4852
4812
  if (prompt) {
4853
4813
  try {
4854
4814
  await this.send(threadId, prompt);
@@ -4859,6 +4819,14 @@ var Orchestrator = class {
4859
4819
  });
4860
4820
  }
4861
4821
  }
4822
+ await setup;
4823
+ const { autoRunAfterSetupEnabled } = await import("../app-settings-F36ISTCF.js");
4824
+ if (autoRunAfterSetupEnabled()) {
4825
+ try {
4826
+ await this.startDev(threadId);
4827
+ } catch {
4828
+ }
4829
+ }
4862
4830
  }
4863
4831
  /** Run workspace setup after a new worktree is created (no-op if none configured). */
4864
4832
  async runSetupAfterCreate(threadId) {
@@ -5113,7 +5081,7 @@ var Orchestrator = class {
5113
5081
  }
5114
5082
  const isBrightsy = fresh.agent === "brightsy";
5115
5083
  const isOrchestration = isOrchestratorThread(fresh);
5116
- const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("../app-settings-PEXK5VEX.js");
5084
+ const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("../app-settings-F36ISTCF.js");
5117
5085
  const gitAuthMode = getGithubGitAuthMode();
5118
5086
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
5119
5087
  githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
@@ -5206,7 +5174,7 @@ var Orchestrator = class {
5206
5174
  if (this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
5207
5175
  const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
5208
5176
  if (sessionId) {
5209
- const { recoverFinishedCursorRun } = await import("../cursor-recover-NNK7JPQM.js");
5177
+ const { recoverFinishedCursorRun } = await import("../cursor-recover-S5ORPW34.js");
5210
5178
  for (let i = 0; i < 8; i++) {
5211
5179
  const recovered = recoverFinishedCursorRun({
5212
5180
  agentId: sessionId,
@@ -5556,7 +5524,7 @@ var Orchestrator = class {
5556
5524
  });
5557
5525
  this.emit({ type: "setup_started", threadId: thread.id });
5558
5526
  try {
5559
- let setup = await runSetupScript(
5527
+ const setup = await runWorkspaceSetup(
5560
5528
  thread.repoPath,
5561
5529
  thread.worktreePath,
5562
5530
  (line) => {
@@ -5564,18 +5532,9 @@ var Orchestrator = class {
5564
5532
  },
5565
5533
  { signal: abort.signal }
5566
5534
  );
5567
- if (!setup.ran) {
5568
- setup = await runCursorWorktreeSetup(
5569
- thread.repoPath,
5570
- thread.worktreePath,
5571
- (line) => {
5572
- this.emit({ type: "setup_output", threadId: thread.id, line });
5573
- }
5574
- );
5575
- }
5576
5535
  if (!setup.ran) {
5577
5536
  throw new Error(
5578
- "No setup script in .sideboard/settings.toml, .conductor/settings.toml, or .cursor/worktrees.json"
5537
+ "No setup script in .sideboard/settings.toml, .conductor/settings.toml, .cursor/worktrees.json, or script/setup (bin/setup, scripts/setup)"
5579
5538
  );
5580
5539
  }
5581
5540
  if (setup.exitCode !== 0 && setup.exitCode !== null) {
@@ -5830,7 +5789,7 @@ var Orchestrator = class {
5830
5789
  updateThread(thread.id, { title: meta.title });
5831
5790
  }
5832
5791
  }
5833
- const { autoArchiveOnMergeEnabled } = await import("../app-settings-PEXK5VEX.js");
5792
+ const { autoArchiveOnMergeEnabled } = await import("../app-settings-F36ISTCF.js");
5834
5793
  const latest = this.requireThread(thread.id);
5835
5794
  if (!shouldAutoArchiveOnPrMerge({
5836
5795
  previousPrState: prevState || null,
@@ -5883,7 +5842,7 @@ var Orchestrator = class {
5883
5842
  this.emit({ type: "status_changed", threadId: t.id, status: t.status });
5884
5843
  }
5885
5844
  for (const id of result.createdThreadIds) {
5886
- await this.runSetupAfterCreate(id);
5845
+ void this.runSetupAfterCreate(id);
5887
5846
  }
5888
5847
  return { stack: result.stack, threads: result.threads };
5889
5848
  }
@@ -5900,7 +5859,7 @@ var Orchestrator = class {
5900
5859
  status: result.thread.status
5901
5860
  });
5902
5861
  if (result.createdWorktree) {
5903
- await this.runSetupAfterCreate(result.thread.id);
5862
+ void this.runSetupAfterCreate(result.thread.id);
5904
5863
  }
5905
5864
  return { stack: result.stack, thread: result.thread };
5906
5865
  }
@@ -5915,7 +5874,7 @@ var Orchestrator = class {
5915
5874
  this.emit({ type: "status_changed", threadId: t.id, status: t.status });
5916
5875
  }
5917
5876
  for (const id of result.createdThreadIds) {
5918
- await this.runSetupAfterCreate(id);
5877
+ void this.runSetupAfterCreate(id);
5919
5878
  }
5920
5879
  return { stack: result.stack, threads: result.threads };
5921
5880
  }
@@ -5926,7 +5885,7 @@ var Orchestrator = class {
5926
5885
  this.emit({ type: "status_changed", threadId: t.id, status: t.status });
5927
5886
  }
5928
5887
  for (const id of result.createdThreadIds) {
5929
- await this.runSetupAfterCreate(id);
5888
+ void this.runSetupAfterCreate(id);
5930
5889
  }
5931
5890
  return { stack: result.stack, threads: result.threads };
5932
5891
  }
@@ -6057,7 +6016,7 @@ var Orchestrator = class {
6057
6016
  async forkThreadWorktree(input) {
6058
6017
  const thread = await forkThreadWorktree(input);
6059
6018
  this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
6060
- await this.runSetupAfterCreate(thread.id);
6019
+ void this.runSetupAfterCreate(thread.id);
6061
6020
  return thread;
6062
6021
  }
6063
6022
  renameThread(threadRef, title) {
@@ -6118,7 +6077,7 @@ var Orchestrator = class {
6118
6077
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
6119
6078
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
6120
6079
  try {
6121
- const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-AIZDG6PS.js");
6080
+ const { ensureWorkspace: ensureWorkspace2 } = await import("../workspaces-J4ULXOUH.js");
6122
6081
  await ensureWorkspace2(thread.repoPath);
6123
6082
  } catch {
6124
6083
  }
@@ -6140,7 +6099,7 @@ var Orchestrator = class {
6140
6099
  await runArchiveScript(thread.repoPath, thread.worktreePath);
6141
6100
  } catch {
6142
6101
  }
6143
- const { deleteBranchOnPurgeEnabled } = await import("../app-settings-PEXK5VEX.js");
6102
+ const { deleteBranchOnPurgeEnabled } = await import("../app-settings-F36ISTCF.js");
6144
6103
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
6145
6104
  await removeWorktree(thread.repoPath, thread.worktreePath, {
6146
6105
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -6154,18 +6113,18 @@ var Orchestrator = class {
6154
6113
  throw new Error("Thread is not archived");
6155
6114
  }
6156
6115
  if (isGlobalThread(thread)) {
6157
- const { globalAgentCwd } = await import("../paths-2OFB7UJG.js");
6116
+ const { globalAgentCwd } = await import("../paths-TZX4L5X7.js");
6158
6117
  updateThread(thread.id, { worktreePath: globalAgentCwd() });
6159
6118
  const restored2 = setStatus(thread.id, "idle");
6160
6119
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
6161
6120
  return restored2;
6162
6121
  }
6163
- if (!existsSync15(thread.worktreePath)) {
6164
- const { createThreadWorktree: createThreadWorktree2 } = await import("../worktree-6ZALJUWG.js");
6165
- const { execa: execa6 } = await import("execa");
6122
+ if (!existsSync14(thread.worktreePath)) {
6123
+ const { createThreadWorktree: createThreadWorktree2 } = await import("../worktree-4Z2VSHAQ.js");
6124
+ const { execa: execa5 } = await import("execa");
6166
6125
  const slug = thread.worktreePath.split("/").pop();
6167
6126
  const dest = thread.worktreePath;
6168
- await execa6("git", ["worktree", "add", dest, thread.branchName], {
6127
+ await execa5("git", ["worktree", "add", dest, thread.branchName], {
6169
6128
  cwd: thread.repoPath
6170
6129
  });
6171
6130
  void createThreadWorktree2;
@@ -7332,7 +7291,7 @@ function withTimeout(promise, ms, label) {
7332
7291
  async function startMcpServer() {
7333
7292
  const orch = getOrchestrator();
7334
7293
  try {
7335
- const { maxConcurrentAgents } = await import("../app-settings-PEXK5VEX.js");
7294
+ const { maxConcurrentAgents } = await import("../app-settings-F36ISTCF.js");
7336
7295
  orch.setMaxConcurrent(maxConcurrentAgents());
7337
7296
  } catch {
7338
7297
  }
@@ -7541,8 +7500,8 @@ async function startMcpServer() {
7541
7500
  registerSlackTools(server);
7542
7501
  registerLinearTools(server);
7543
7502
  if (sideboardMcpProfile() !== "worktree") {
7544
- const { getCaffeinateHold, setCaffeinateHold } = await import("../caffeinate-hold-OHAUWOA6.js");
7545
- const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults } = await import("../app-settings-PEXK5VEX.js");
7503
+ const { getCaffeinateHold, setCaffeinateHold } = await import("../caffeinate-hold-U3QJBV67.js");
7504
+ const { resolveNewThreadOptions: resolveNewThreadOptions2, resolveThreadDefaults } = await import("../app-settings-F36ISTCF.js");
7546
7505
  const accountDefaults = resolveThreadDefaults();
7547
7506
  const accountDefaultsHint = `Account defaults: agent=${accountDefaults.agent}, model=${accountDefaults.model?.trim() || "Auto"}, effort=${accountDefaults.effort}`;
7548
7507
  server.tool(
@@ -7585,7 +7544,7 @@ async function startMcpServer() {
7585
7544
  );
7586
7545
  server.tool(
7587
7546
  "create_thread",
7588
- `Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces. From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Then use send_to_thread to chat.`,
7547
+ `Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces. From an orchestration chat, omit parentThreadId (Sideboard binds the child to this chat) or pass the exact id from the turn reminder \u2014 never invent a uuid. Prefer omitting agent/model so Sideboard applies ${accountDefaultsHint}. Setup (settings.toml, .cursor/worktrees.json, or script/setup) runs in the background in parallel with the first turn. Then use send_to_thread to chat.`,
7589
7548
  {
7590
7549
  sourceType: z3.enum(["branch", "pr", "ticket"]),
7591
7550
  sourceRef: z3.string(),
@@ -8103,7 +8062,7 @@ async function startMcpServer() {
8103
8062
  );
8104
8063
  server.tool(
8105
8064
  "run_setup",
8106
- "Re-run workspace setup (Sideboard/Conductor settings or .cursor/worktrees.json)",
8065
+ "Re-run workspace setup (Sideboard/Conductor settings, .cursor/worktrees.json, or script/setup). New worktrees already run this automatically.",
8107
8066
  { ref: z3.string() },
8108
8067
  async ({ ref }) => {
8109
8068
  const result = await orch.runSetup(ref);