@sideboard-ai/core 0.1.86 → 0.1.88

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 (52) hide show
  1. package/dist/agents/cursor-runner.cjs +23 -13
  2. package/dist/agents/cursor-runner.js +2 -2
  3. package/dist/{agents-NDHD3VOL.js → agents-LMUFTGKF.js} +8 -8
  4. package/dist/{agents-HJ3Y2JN5.js → agents-ODBP7J6E.js} +9 -9
  5. package/dist/{app-settings-K6RFCRF6.js → app-settings-BRF7VKTQ.js} +3 -3
  6. package/dist/{app-settings-PEXK5VEX.js → app-settings-ZXPAB3QN.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-FWJYLBO6.js → chunk-3WA37BRI.js} +1 -1
  10. package/dist/{chunk-IGEL6M4G.js → chunk-6EZRSCIT.js} +3 -3
  11. package/dist/{chunk-AY53MPDE.js → chunk-6LFV4VFI.js} +15 -2
  12. package/dist/{chunk-OBHZKT2T.js → chunk-7D27DD2X.js} +3 -3
  13. package/dist/{chunk-RV6DBEDQ.js → chunk-7KDBDMNC.js} +1 -1
  14. package/dist/{chunk-U4RZ3IQI.js → chunk-B2KIO2SD.js} +5 -5
  15. package/dist/{chunk-M37RITA6.js → chunk-B4R2VB2A.js} +164 -30
  16. package/dist/{chunk-6K5VAPVR.js → chunk-DKHGWYWR.js} +1 -1
  17. package/dist/{chunk-I3FRXL7J.js → chunk-FT2SQOL4.js} +2 -2
  18. package/dist/{chunk-KE6QLNTJ.js → chunk-JE75QW2I.js} +58 -24
  19. package/dist/{chunk-7MV3RXSC.js → chunk-JL4SJ6V7.js} +137 -26
  20. package/dist/{chunk-7FD7COKE.js → chunk-JOF3XIEM.js} +1 -1
  21. package/dist/{chunk-MFF2RE3I.js → chunk-NZPGMNFC.js} +1 -1
  22. package/dist/{chunk-HA2QTIWN.js → chunk-OB6IRIFV.js} +5 -5
  23. package/dist/{chunk-HHTHF5BQ.js → chunk-QSLE4VEM.js} +4 -4
  24. package/dist/{chunk-4Y745GLN.js → chunk-RJLBSYUO.js} +59 -25
  25. package/dist/{chunk-5KLC2MWZ.js → chunk-TLPJHLLM.js} +14 -1
  26. package/dist/{chunk-EWKHP6DD.js → chunk-UHTNJKZX.js} +5 -5
  27. package/dist/{chunk-ZN4NDAHV.js → chunk-VZ2L4AEJ.js} +5 -5
  28. package/dist/{chunk-45U4RQ74.js → chunk-WANQFU3S.js} +3 -3
  29. package/dist/{chunk-6ZGTM2E7.js → chunk-ZXYWWSHZ.js} +3 -3
  30. package/dist/{connected-teams-BNBM7OIC.js → connected-teams-SWHJWK2A.js} +2 -2
  31. package/dist/{connected-teams-LSQ5TAZP.js → connected-teams-TLVKZPJP.js} +2 -2
  32. package/dist/{coordinator-prompt-L65MIGCV.js → coordinator-prompt-CI5SHONJ.js} +5 -5
  33. package/dist/{coordinator-prompt-HOMHBR2L.js → coordinator-prompt-UK5LYFN5.js} +6 -6
  34. package/dist/{cursor-recover-L5PNQUDT.js → cursor-recover-G34BYKL2.js} +1 -1
  35. package/dist/{cursor-recover-NNK7JPQM.js → cursor-recover-S5ORPW34.js} +1 -1
  36. package/dist/{global-workspace-MXOLTUAR.js → global-workspace-2YZ2V4I5.js} +6 -6
  37. package/dist/{global-workspace-VGKPYFE2.js → global-workspace-JQQLPJM5.js} +7 -7
  38. package/dist/index.cjs +693 -541
  39. package/dist/index.d.cts +43 -9
  40. package/dist/index.d.ts +43 -9
  41. package/dist/index.js +213 -253
  42. package/dist/mcp/run-stdio.cjs +630 -505
  43. package/dist/mcp/run-stdio.js +184 -225
  44. package/dist/{paths-VPH3ITBK.js → paths-JQM2XRAD.js} +1 -1
  45. package/dist/{paths-2OFB7UJG.js → paths-TZX4L5X7.js} +1 -1
  46. package/dist/{thread-store-BUBR24YA.js → thread-store-V7NOOXKE.js} +2 -2
  47. package/dist/{thread-store-XTPFCJAI.js → thread-store-XAKWCV2E.js} +2 -2
  48. package/dist/{workspaces-VWQ5YSND.js → workspaces-FDO5L4NI.js} +7 -7
  49. package/dist/{workspaces-2GZ2VNNU.js → workspaces-YWCC3WV4.js} +8 -8
  50. package/dist/{worktree-RFCCG23P.js → worktree-4555QBQ7.js} +4 -4
  51. package/dist/{worktree-WZJ3CFEN.js → worktree-7YNSJ224.js} +5 -5
  52. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -78,10 +78,139 @@ var init_thinking_effort = __esm({
78
78
  }
79
79
  });
80
80
 
81
+ // src/hook/convention-setup.ts
82
+ function isFile(path2) {
83
+ try {
84
+ return (0, import_node_fs.statSync)(path2).isFile();
85
+ } catch {
86
+ return false;
87
+ }
88
+ }
89
+ function normPath(p) {
90
+ return p.replace(/\/+$/, "");
91
+ }
92
+ function findConventionSetup(worktreePath, repoPath) {
93
+ const roots = [
94
+ { root: worktreePath, where: "worktree" }
95
+ ];
96
+ if (repoPath && normPath(repoPath) !== normPath(worktreePath)) {
97
+ roots.push({ root: repoPath, where: "main repo" });
98
+ }
99
+ for (const { root, where } of roots) {
100
+ for (const relPath of CONVENTION_SETUP_RELPATHS) {
101
+ const absPath = (0, import_node_path.join)(root, relPath);
102
+ if (!(0, import_node_fs.existsSync)(absPath) || !isFile(absPath)) continue;
103
+ return {
104
+ relPath,
105
+ absPath,
106
+ command: `bash ${JSON.stringify(absPath)}`,
107
+ source: `${relPath} (${where})`
108
+ };
109
+ }
110
+ }
111
+ return null;
112
+ }
113
+ function hasConventionSetup(worktreePath, repoPath) {
114
+ return findConventionSetup(worktreePath, repoPath) !== null;
115
+ }
116
+ var import_node_fs, import_node_path, CONVENTION_SETUP_RELPATHS;
117
+ var init_convention_setup = __esm({
118
+ "src/hook/convention-setup.ts"() {
119
+ "use strict";
120
+ import_node_fs = require("fs");
121
+ import_node_path = require("path");
122
+ CONVENTION_SETUP_RELPATHS = [
123
+ "script/setup",
124
+ "bin/setup",
125
+ "scripts/setup.sh",
126
+ "scripts/setup"
127
+ ];
128
+ }
129
+ });
130
+
131
+ // src/hook/cursor-worktrees.ts
132
+ function loadCursorWorktreesJson(rootPath) {
133
+ const path2 = (0, import_node_path2.join)(rootPath, ".cursor", "worktrees.json");
134
+ if (!(0, import_node_fs2.existsSync)(path2)) return null;
135
+ try {
136
+ return JSON.parse((0, import_node_fs2.readFileSync)(path2, "utf8"));
137
+ } catch {
138
+ return null;
139
+ }
140
+ }
141
+ function resolveSetupSpec(config) {
142
+ if (process.platform === "win32") {
143
+ return config["setup-worktree-windows"] ?? config["setup-worktree"] ?? null;
144
+ }
145
+ return config["setup-worktree-unix"] ?? config["setup-worktree"] ?? null;
146
+ }
147
+ async function runCursorWorktreeSetup(repoPath, worktreePath, onLine) {
148
+ const fromWorktree = loadCursorWorktreesJson(worktreePath);
149
+ const fromRepo = worktreePath !== repoPath ? loadCursorWorktreesJson(repoPath) : null;
150
+ const config = fromWorktree ?? fromRepo;
151
+ if (!config) return { ran: false, exitCode: null, source: null };
152
+ const spec = resolveSetupSpec(config);
153
+ if (!spec) return { ran: false, exitCode: null, source: null };
154
+ const sourceLabel = fromWorktree ? ".cursor/worktrees.json (worktree)" : ".cursor/worktrees.json (main repo)";
155
+ const env = {
156
+ ...process.env,
157
+ ROOT_WORKTREE_PATH: repoPath
158
+ };
159
+ if (process.platform === "win32") {
160
+ env.ROOT_WORKTREE_PATH = repoPath;
161
+ }
162
+ const commands = Array.isArray(spec) ? spec : [spec.endsWith(".sh") || spec.endsWith(".ps1") ? (0, import_node_path2.join)(
163
+ fromWorktree ? worktreePath : repoPath,
164
+ ".cursor",
165
+ spec
166
+ ) : spec];
167
+ let lastExit = 0;
168
+ for (const command of commands) {
169
+ const isScriptPath = typeof spec === "string" && (spec.endsWith(".sh") || spec.endsWith(".ps1"));
170
+ const shell = process.platform === "win32" ? "powershell" : "bash";
171
+ const args = process.platform === "win32" ? isScriptPath ? ["-File", command] : ["-Command", command] : isScriptPath ? [command] : ["-lc", command];
172
+ onLine?.(`[cursor setup] ${command}`);
173
+ const child = (0, import_execa.execa)(shell, args, {
174
+ cwd: worktreePath,
175
+ reject: false,
176
+ env
177
+ });
178
+ if (child.stdout && onLine) {
179
+ const rl = (0, import_node_readline.createInterface)({ input: child.stdout });
180
+ rl.on("line", onLine);
181
+ }
182
+ if (child.stderr && onLine) {
183
+ const rl = (0, import_node_readline.createInterface)({ input: child.stderr });
184
+ rl.on("line", onLine);
185
+ }
186
+ const result = await child;
187
+ lastExit = result.exitCode ?? null;
188
+ if (lastExit !== 0 && lastExit !== null) break;
189
+ }
190
+ return { ran: true, exitCode: lastExit, source: sourceLabel };
191
+ }
192
+ function hasCursorWorktreeSetup(worktreePath, repoPath) {
193
+ if (loadCursorWorktreesJson(worktreePath)) return true;
194
+ if (repoPath && repoPath !== worktreePath && loadCursorWorktreesJson(repoPath)) {
195
+ return true;
196
+ }
197
+ return false;
198
+ }
199
+ var import_node_fs2, import_node_path2, import_execa, import_node_readline;
200
+ var init_cursor_worktrees = __esm({
201
+ "src/hook/cursor-worktrees.ts"() {
202
+ "use strict";
203
+ import_node_fs2 = require("fs");
204
+ import_node_path2 = require("path");
205
+ import_execa = require("execa");
206
+ import_node_readline = require("readline");
207
+ }
208
+ });
209
+
81
210
  // src/hook/settings.ts
82
211
  function expandHome(path2) {
83
212
  if (path2.startsWith("~/") || path2 === "~") {
84
- return (0, import_node_path.join)((0, import_node_os.homedir)(), path2.slice(2));
213
+ return (0, import_node_path3.join)((0, import_node_os.homedir)(), path2.slice(2));
85
214
  }
86
215
  return path2;
87
216
  }
@@ -94,8 +223,8 @@ function parseAvailableIn(raw) {
94
223
  return out.length ? out : void 0;
95
224
  }
96
225
  function parseSettingsFile(path2, source) {
97
- if (!(0, import_node_fs.existsSync)(path2)) return null;
98
- const raw = (0, import_node_fs.readFileSync)(path2, "utf8");
226
+ if (!(0, import_node_fs3.existsSync)(path2)) return null;
227
+ const raw = (0, import_node_fs3.readFileSync)(path2, "utf8");
99
228
  const data = (0, import_smol_toml.parse)(raw);
100
229
  const scripts = data.scripts ?? {};
101
230
  const setup = typeof scripts.setup === "string" ? scripts.setup : void 0;
@@ -198,15 +327,15 @@ function finalizeSettings(parsed) {
198
327
  };
199
328
  }
200
329
  function familyFiles(rootPath, source) {
201
- const dir = (0, import_node_path.join)(rootPath, `.${source}`);
330
+ const dir = (0, import_node_path3.join)(rootPath, `.${source}`);
202
331
  return {
203
- toml: (0, import_node_path.join)(dir, "settings.toml"),
204
- local: (0, import_node_path.join)(dir, "settings.local.toml")
332
+ toml: (0, import_node_path3.join)(dir, "settings.toml"),
333
+ local: (0, import_node_path3.join)(dir, "settings.local.toml")
205
334
  };
206
335
  }
207
336
  function familyExists(rootPath, source) {
208
337
  const files = familyFiles(rootPath, source);
209
- return (0, import_node_fs.existsSync)(files.toml) || (0, import_node_fs.existsSync)(files.local);
338
+ return (0, import_node_fs3.existsSync)(files.toml) || (0, import_node_fs3.existsSync)(files.local);
210
339
  }
211
340
  function detectFamily(rootPath) {
212
341
  if (familyExists(rootPath, "sideboard")) return "sideboard";
@@ -225,7 +354,7 @@ function loadAnyLocal(rootPath) {
225
354
  loadLocalToml(rootPath, "sideboard")
226
355
  );
227
356
  }
228
- function normPath(p) {
357
+ function normPath2(p) {
229
358
  return p.replace(/\/+$/, "");
230
359
  }
231
360
  function loadRepoSettings(repoPath) {
@@ -239,11 +368,11 @@ function loadRepoSettings(repoPath) {
239
368
  }
240
369
  function loadWorkspaceSettings(worktreePath, repoPath) {
241
370
  const wtFamily = detectFamily(worktreePath);
242
- const repoFamily = repoPath && normPath(repoPath) !== normPath(worktreePath) ? detectFamily(repoPath) : null;
371
+ const repoFamily = repoPath && normPath2(repoPath) !== normPath2(worktreePath) ? detectFamily(repoPath) : null;
243
372
  const wtToml = wtFamily ? loadCommittedToml(worktreePath, wtFamily) : null;
244
373
  const repoToml = repoPath && repoFamily ? loadCommittedToml(repoPath, repoFamily) : null;
245
374
  let merged = wtToml ?? repoToml;
246
- if (repoPath && normPath(repoPath) !== normPath(worktreePath)) {
375
+ if (repoPath && normPath2(repoPath) !== normPath2(worktreePath)) {
247
376
  merged = mergeSettings(merged, loadAnyLocal(repoPath));
248
377
  }
249
378
  merged = mergeSettings(merged, loadAnyLocal(worktreePath));
@@ -257,7 +386,7 @@ function hasRepoHook(repoPath) {
257
386
  }
258
387
  function hasWorkspaceHook(worktreePath, repoPath) {
259
388
  if (hasRepoHook(worktreePath)) return true;
260
- if (repoPath && normPath(repoPath) !== normPath(worktreePath) && hasRepoHook(repoPath)) {
389
+ if (repoPath && normPath2(repoPath) !== normPath2(worktreePath) && hasRepoHook(repoPath)) {
261
390
  return true;
262
391
  }
263
392
  return false;
@@ -269,16 +398,16 @@ function settingsSourceLabel(rootPath) {
269
398
  const family = detectFamily(rootPath);
270
399
  if (!family) return null;
271
400
  const files = familyFiles(rootPath, family);
272
- if ((0, import_node_fs.existsSync)(files.toml) && (0, import_node_fs.existsSync)(files.local)) {
401
+ if ((0, import_node_fs3.existsSync)(files.toml) && (0, import_node_fs3.existsSync)(files.local)) {
273
402
  return `.${family}/settings.toml + local`;
274
403
  }
275
- if ((0, import_node_fs.existsSync)(files.local)) return `.${family}/settings.local.toml`;
404
+ if ((0, import_node_fs3.existsSync)(files.local)) return `.${family}/settings.local.toml`;
276
405
  return `.${family}/settings.toml`;
277
406
  }
278
407
  function workspaceSettingsSourceLabel(worktreePath, repoPath) {
279
408
  const wt = settingsSourceLabel(worktreePath);
280
409
  if (wt) return `${wt} (worktree)`;
281
- if (repoPath && normPath(repoPath) !== normPath(worktreePath)) {
410
+ if (repoPath && normPath2(repoPath) !== normPath2(worktreePath)) {
282
411
  const repo = settingsSourceLabel(repoPath);
283
412
  if (repo) return `${repo} (main repo)`;
284
413
  }
@@ -286,20 +415,32 @@ function workspaceSettingsSourceLabel(worktreePath, repoPath) {
286
415
  }
287
416
  function getRepoSetupInfo(worktreePath, repoPath) {
288
417
  const settings = loadWorkspaceSettings(worktreePath, repoPath);
418
+ const convention = findConventionSetup(worktreePath, repoPath);
419
+ const cursor = hasCursorWorktreeSetup(worktreePath, repoPath);
420
+ const hasSetupScript = Boolean(settings?.setup) || cursor || Boolean(convention);
421
+ let configLabel = workspaceSettingsSourceLabel(worktreePath, repoPath);
422
+ if (!settings?.setup) {
423
+ if (convention) configLabel = convention.source;
424
+ else if (cursor) {
425
+ configLabel = hasCursorWorktreeSetup(worktreePath) ? ".cursor/worktrees.json (worktree)" : ".cursor/worktrees.json (main repo)";
426
+ }
427
+ }
289
428
  return {
290
- hasConfig: hasWorkspaceHook(worktreePath, repoPath),
291
- hasSetupScript: Boolean(settings?.setup),
292
- configLabel: workspaceSettingsSourceLabel(worktreePath, repoPath)
429
+ hasConfig: hasWorkspaceHook(worktreePath, repoPath) || cursor || Boolean(convention),
430
+ hasSetupScript,
431
+ configLabel
293
432
  };
294
433
  }
295
- var import_node_fs, import_node_os, import_node_path, import_smol_toml;
434
+ var import_node_fs3, import_node_os, import_node_path3, import_smol_toml;
296
435
  var init_settings = __esm({
297
436
  "src/hook/settings.ts"() {
298
437
  "use strict";
299
- import_node_fs = require("fs");
438
+ import_node_fs3 = require("fs");
300
439
  import_node_os = require("os");
301
- import_node_path = require("path");
440
+ import_node_path3 = require("path");
302
441
  import_smol_toml = require("smol-toml");
442
+ init_convention_setup();
443
+ init_cursor_worktrees();
303
444
  }
304
445
  });
305
446
 
@@ -320,67 +461,67 @@ __export(paths_exports, {
320
461
  });
321
462
  function appDataDir() {
322
463
  const override = process.env.SIDEBOARD_APP_DATA?.trim();
323
- const base = override ? override : process.platform === "darwin" ? (0, import_node_path3.join)((0, import_node_os2.homedir)(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? (0, import_node_path3.join)(process.env.APPDATA ?? (0, import_node_path3.join)((0, import_node_os2.homedir)(), "AppData", "Roaming"), "sideboard") : (0, import_node_path3.join)((0, import_node_os2.homedir)(), ".local", "share", "sideboard");
324
- (0, import_node_fs2.mkdirSync)(base, { recursive: true });
464
+ const base = override ? override : process.platform === "darwin" ? (0, import_node_path5.join)((0, import_node_os2.homedir)(), "Library", "Application Support", "sideboard") : process.platform === "win32" ? (0, import_node_path5.join)(process.env.APPDATA ?? (0, import_node_path5.join)((0, import_node_os2.homedir)(), "AppData", "Roaming"), "sideboard") : (0, import_node_path5.join)((0, import_node_os2.homedir)(), ".local", "share", "sideboard");
465
+ (0, import_node_fs4.mkdirSync)(base, { recursive: true });
325
466
  return base;
326
467
  }
327
468
  function threadsDir() {
328
- const dir = (0, import_node_path3.join)(appDataDir(), "threads");
329
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
469
+ const dir = (0, import_node_path5.join)(appDataDir(), "threads");
470
+ (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
330
471
  return dir;
331
472
  }
332
473
  function locksDir() {
333
- const dir = (0, import_node_path3.join)(appDataDir(), "locks");
334
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
474
+ const dir = (0, import_node_path5.join)(appDataDir(), "locks");
475
+ (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
335
476
  return dir;
336
477
  }
337
478
  function sideboardHomeDir() {
338
- const dir = (0, import_node_path3.join)((0, import_node_os2.homedir)(), "sideboard");
339
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
479
+ const dir = (0, import_node_path5.join)((0, import_node_os2.homedir)(), "sideboard");
480
+ (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
340
481
  return dir;
341
482
  }
342
483
  function sideboardReposDir() {
343
- const dir = (0, import_node_path3.join)(sideboardHomeDir(), "repos");
344
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
484
+ const dir = (0, import_node_path5.join)(sideboardHomeDir(), "repos");
485
+ (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
345
486
  return dir;
346
487
  }
347
488
  function sideboardWorkspacesDir() {
348
- const dir = (0, import_node_path3.join)(sideboardHomeDir(), "workspaces");
349
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
489
+ const dir = (0, import_node_path5.join)(sideboardHomeDir(), "workspaces");
490
+ (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
350
491
  return dir;
351
492
  }
352
493
  function repoSlug(repoPath) {
353
- return (0, import_node_path2.basename)(repoPath.replace(/\/$/, "")) || "repo";
494
+ return (0, import_node_path4.basename)(repoPath.replace(/\/$/, "")) || "repo";
354
495
  }
355
496
  function worktreesRoot(repoPath) {
356
497
  const settings = loadRepoSettings(repoPath);
357
498
  if (settings?.worktreesRoot) {
358
- (0, import_node_fs2.mkdirSync)(settings.worktreesRoot, { recursive: true });
499
+ (0, import_node_fs4.mkdirSync)(settings.worktreesRoot, { recursive: true });
359
500
  return settings.worktreesRoot;
360
501
  }
361
- const dir = (0, import_node_path3.join)(sideboardWorkspacesDir(), repoSlug(repoPath));
362
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
502
+ const dir = (0, import_node_path5.join)(sideboardWorkspacesDir(), repoSlug(repoPath));
503
+ (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
363
504
  return dir;
364
505
  }
365
506
  function threadFilePath(id) {
366
- return (0, import_node_path3.join)(threadsDir(), `${id}.json`);
507
+ return (0, import_node_path5.join)(threadsDir(), `${id}.json`);
367
508
  }
368
509
  function threadLockPath(id) {
369
- return (0, import_node_path3.join)(locksDir(), `${id}.lock`);
510
+ return (0, import_node_path5.join)(locksDir(), `${id}.lock`);
370
511
  }
371
512
  function globalAgentCwd() {
372
- const dir = (0, import_node_path3.join)(appDataDir(), "global");
373
- (0, import_node_fs2.mkdirSync)(dir, { recursive: true });
513
+ const dir = (0, import_node_path5.join)(appDataDir(), "global");
514
+ (0, import_node_fs4.mkdirSync)(dir, { recursive: true });
374
515
  return dir;
375
516
  }
376
- var import_node_path2, import_node_os2, import_node_path3, import_node_fs2;
517
+ var import_node_path4, import_node_os2, import_node_path5, import_node_fs4;
377
518
  var init_paths = __esm({
378
519
  "src/store/paths.ts"() {
379
520
  "use strict";
380
- import_node_path2 = require("path");
521
+ import_node_path4 = require("path");
381
522
  import_node_os2 = require("os");
382
- import_node_path3 = require("path");
383
- import_node_fs2 = require("fs");
523
+ import_node_path5 = require("path");
524
+ import_node_fs4 = require("fs");
384
525
  init_settings();
385
526
  }
386
527
  });
@@ -406,6 +547,18 @@ function wrapElectronAsNodeLaunch(file, args) {
406
547
  function isStrippedElectronLaunch(command, args) {
407
548
  return command === "/bin/sh" && Boolean(args?.[1]?.includes("ELECTRON_RUN_AS_NODE") && args[1].includes("unset"));
408
549
  }
550
+ function isElectronLikeCommand(command) {
551
+ const name = command.trim();
552
+ if (!name) return false;
553
+ if (process.versions.electron && name === process.execPath) return true;
554
+ return /(?:^|[/\\])Electron(?:\.exe)?$/i.test(name) || /Sideboard\.app[/\\]/i.test(name) || /Electron\.app[/\\]/i.test(name);
555
+ }
556
+ function unwrapStrippedElectronLaunch(command, args) {
557
+ if (!isStrippedElectronLaunch(command, args) || !args || args.length < 4) {
558
+ return null;
559
+ }
560
+ return { file: args[3], args: args.slice(4) };
561
+ }
409
562
  var NESTED_ELECTRON_ENV_PREFIXES, STRIP_NESTED_ELECTRON_THEN_EXEC;
410
563
  var init_nested_electron_env = __esm({
411
564
  "src/hook/nested-electron-env.ts"() {
@@ -422,22 +575,22 @@ var init_nested_electron_env = __esm({
422
575
 
423
576
  // src/store/private-file.ts
424
577
  function writePrivateFile(path2, contents) {
425
- (0, import_node_fs3.mkdirSync)((0, import_node_path4.dirname)(path2), { recursive: true });
426
- (0, import_node_fs3.writeFileSync)(path2, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
578
+ (0, import_node_fs5.mkdirSync)((0, import_node_path6.dirname)(path2), { recursive: true });
579
+ (0, import_node_fs5.writeFileSync)(path2, contents, { encoding: "utf8", mode: PRIVATE_FILE_MODE });
427
580
  chmodOwnerOnly(path2);
428
581
  }
429
582
  function chmodOwnerOnly(path2) {
430
583
  try {
431
- (0, import_node_fs3.chmodSync)(path2, PRIVATE_FILE_MODE);
584
+ (0, import_node_fs5.chmodSync)(path2, PRIVATE_FILE_MODE);
432
585
  } catch {
433
586
  }
434
587
  }
435
- var import_node_fs3, import_node_path4, PRIVATE_FILE_MODE;
588
+ var import_node_fs5, import_node_path6, PRIVATE_FILE_MODE;
436
589
  var init_private_file = __esm({
437
590
  "src/store/private-file.ts"() {
438
591
  "use strict";
439
- import_node_fs3 = require("fs");
440
- import_node_path4 = require("path");
592
+ import_node_fs5 = require("fs");
593
+ import_node_path6 = require("path");
441
594
  PRIVATE_FILE_MODE = 384;
442
595
  }
443
596
  });
@@ -529,11 +682,11 @@ function decryptEnvelope(envelope, key) {
529
682
  return JSON.parse(plaintext.toString("utf8"));
530
683
  }
531
684
  function readSecureJson(path2) {
532
- if (!(0, import_node_fs4.existsSync)(path2)) return null;
685
+ if (!(0, import_node_fs6.existsSync)(path2)) return null;
533
686
  chmodOwnerOnly(path2);
534
687
  let parsed;
535
688
  try {
536
- parsed = JSON.parse((0, import_node_fs4.readFileSync)(path2, "utf8"));
689
+ parsed = JSON.parse((0, import_node_fs6.readFileSync)(path2, "utf8"));
537
690
  } catch {
538
691
  return null;
539
692
  }
@@ -553,17 +706,17 @@ function writeSecureJson(path2, value) {
553
706
  `);
554
707
  }
555
708
  function isSecureFileEncrypted(path2) {
556
- if (!(0, import_node_fs4.existsSync)(path2)) return false;
709
+ if (!(0, import_node_fs6.existsSync)(path2)) return false;
557
710
  try {
558
- return isEnvelope(JSON.parse((0, import_node_fs4.readFileSync)(path2, "utf8")));
711
+ return isEnvelope(JSON.parse((0, import_node_fs6.readFileSync)(path2, "utf8")));
559
712
  } catch {
560
713
  return false;
561
714
  }
562
715
  }
563
716
  function secureFileUnlocksWith(path2, key) {
564
- if (!(0, import_node_fs4.existsSync)(path2) || key.length !== 32) return true;
717
+ if (!(0, import_node_fs6.existsSync)(path2) || key.length !== 32) return true;
565
718
  try {
566
- const parsed = JSON.parse((0, import_node_fs4.readFileSync)(path2, "utf8"));
719
+ const parsed = JSON.parse((0, import_node_fs6.readFileSync)(path2, "utf8"));
567
720
  if (!isEnvelope(parsed)) return true;
568
721
  decryptEnvelope(parsed, key);
569
722
  return true;
@@ -571,13 +724,13 @@ function secureFileUnlocksWith(path2, key) {
571
724
  return false;
572
725
  }
573
726
  }
574
- var import_node_child_process, import_node_crypto, import_node_fs4, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, ALG, injectedKey;
727
+ var import_node_child_process, import_node_crypto, import_node_fs6, KEYCHAIN_SERVICE, KEYCHAIN_ACCOUNT, ALG, injectedKey;
575
728
  var init_secure_file = __esm({
576
729
  "src/store/secure-file.ts"() {
577
730
  "use strict";
578
731
  import_node_child_process = require("child_process");
579
732
  import_node_crypto = require("crypto");
580
- import_node_fs4 = require("fs");
733
+ import_node_fs6 = require("fs");
581
734
  init_private_file();
582
735
  KEYCHAIN_SERVICE = "ai.sideboard.app";
583
736
  KEYCHAIN_ACCOUNT = "secret-vault-v1";
@@ -588,7 +741,7 @@ var init_secure_file = __esm({
588
741
 
589
742
  // src/store/secret-vault.ts
590
743
  function secretVaultPath() {
591
- return (0, import_node_path5.join)(appDataDir(), "secrets.json");
744
+ return (0, import_node_path7.join)(appDataDir(), "secrets.json");
592
745
  }
593
746
  function loadSecretVault() {
594
747
  const parsed = readSecureJson(secretVaultPath());
@@ -632,11 +785,11 @@ function normalizeVault(raw) {
632
785
  }
633
786
  return out;
634
787
  }
635
- var import_node_path5;
788
+ var import_node_path7;
636
789
  var init_secret_vault = __esm({
637
790
  "src/store/secret-vault.ts"() {
638
791
  "use strict";
639
- import_node_path5 = require("path");
792
+ import_node_path7 = require("path");
640
793
  init_paths();
641
794
  init_secure_file();
642
795
  }
@@ -737,10 +890,10 @@ function toPublicAppSettings(settings) {
737
890
  };
738
891
  }
739
892
  function appSettingsPath() {
740
- return (0, import_node_path6.join)(appDataDir(), "settings.json");
893
+ return (0, import_node_path8.join)(appDataDir(), "settings.json");
741
894
  }
742
895
  function claudeUserSettingsPath() {
743
- return (0, import_node_path6.join)((0, import_node_os3.homedir)(), ".claude", "settings.json");
896
+ return (0, import_node_path8.join)((0, import_node_os3.homedir)(), ".claude", "settings.json");
744
897
  }
745
898
  function normalizeClaude(raw) {
746
899
  if (!raw || typeof raw !== "object") return {};
@@ -983,10 +1136,10 @@ function normalizeSettings(raw) {
983
1136
  }
984
1137
  function readSettingsFile() {
985
1138
  const path2 = appSettingsPath();
986
- if (!(0, import_node_fs5.existsSync)(path2)) return { ...EMPTY_SETTINGS };
1139
+ if (!(0, import_node_fs7.existsSync)(path2)) return { ...EMPTY_SETTINGS };
987
1140
  try {
988
1141
  chmodOwnerOnly(path2);
989
- const parsed = JSON.parse((0, import_node_fs5.readFileSync)(path2, "utf8"));
1142
+ const parsed = JSON.parse((0, import_node_fs7.readFileSync)(path2, "utf8"));
990
1143
  return normalizeSettings(parsed);
991
1144
  } catch {
992
1145
  return { ...EMPTY_SETTINGS };
@@ -1546,14 +1699,14 @@ function childEnvWithAppSettings(extra) {
1546
1699
  function harnessEnvKey(harness) {
1547
1700
  return HARNESS_ENV_KEYS[harness];
1548
1701
  }
1549
- var import_node_crypto2, import_node_fs5, import_node_os3, import_node_path6, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, DEFAULT_CLI_BIN;
1702
+ var import_node_crypto2, import_node_fs7, import_node_os3, import_node_path8, HARNESS_ENV_KEYS, DEFAULT_AGENTS, GITHUB_GIT_AUTH_MODES, CLOUD_CONNECT_AGENTS, ISSUE_SOURCES, GIT_AUTH_MODES, EMPTY_SETTINGS, DEFAULT_CLI_BIN;
1550
1703
  var init_app_settings = __esm({
1551
1704
  "src/store/app-settings.ts"() {
1552
1705
  "use strict";
1553
1706
  import_node_crypto2 = require("crypto");
1554
- import_node_fs5 = require("fs");
1707
+ import_node_fs7 = require("fs");
1555
1708
  import_node_os3 = require("os");
1556
- import_node_path6 = require("path");
1709
+ import_node_path8 = require("path");
1557
1710
  init_thinking_effort();
1558
1711
  init_nested_electron_env();
1559
1712
  init_paths();
@@ -1615,7 +1768,7 @@ function setCaffeinateHoldHooks(next) {
1615
1768
  hooks = next;
1616
1769
  }
1617
1770
  function caffeinateHoldPath() {
1618
- return (0, import_node_path7.join)(appDataDir(), "caffeinate-hold.json");
1771
+ return (0, import_node_path9.join)(appDataDir(), "caffeinate-hold.json");
1619
1772
  }
1620
1773
  function processAlive(pid) {
1621
1774
  if (hooks.processAlive) return hooks.processAlive(pid);
@@ -1649,9 +1802,9 @@ function uniqueIds(ids) {
1649
1802
  }
1650
1803
  function readHold() {
1651
1804
  const path2 = caffeinateHoldPath();
1652
- if (!(0, import_node_fs6.existsSync)(path2)) return null;
1805
+ if (!(0, import_node_fs8.existsSync)(path2)) return null;
1653
1806
  try {
1654
- const parsed = JSON.parse((0, import_node_fs6.readFileSync)(path2, "utf8"));
1807
+ const parsed = JSON.parse((0, import_node_fs8.readFileSync)(path2, "utf8"));
1655
1808
  if (typeof parsed?.pid === "number" && parsed.pid > 0) {
1656
1809
  return {
1657
1810
  pid: parsed.pid,
@@ -1673,7 +1826,7 @@ function writeHold(pid, threadIds) {
1673
1826
  }
1674
1827
  function clearHold() {
1675
1828
  try {
1676
- (0, import_node_fs6.unlinkSync)(caffeinateHoldPath());
1829
+ (0, import_node_fs8.unlinkSync)(caffeinateHoldPath());
1677
1830
  } catch {
1678
1831
  }
1679
1832
  }
@@ -1758,13 +1911,13 @@ function releaseCaffeinateHoldForThread(threadId) {
1758
1911
  }
1759
1912
  return setCaffeinateHold(false, { threadId: id });
1760
1913
  }
1761
- var import_node_child_process2, import_node_fs6, import_node_path7, hooks;
1914
+ var import_node_child_process2, import_node_fs8, import_node_path9, hooks;
1762
1915
  var init_caffeinate_hold = __esm({
1763
1916
  "src/store/caffeinate-hold.ts"() {
1764
1917
  "use strict";
1765
1918
  import_node_child_process2 = require("child_process");
1766
- import_node_fs6 = require("fs");
1767
- import_node_path7 = require("path");
1919
+ import_node_fs8 = require("fs");
1920
+ import_node_path9 = require("path");
1768
1921
  init_paths();
1769
1922
  init_private_file();
1770
1923
  hooks = {};
@@ -1858,7 +2011,7 @@ function createEmptyThread(partial) {
1858
2011
  }
1859
2012
  async function withThreadLock(id, fn) {
1860
2013
  const lockPath = threadLockPath(id);
1861
- (0, import_node_fs7.writeFileSync)(lockPath, "", { flag: "a" });
2014
+ (0, import_node_fs9.writeFileSync)(lockPath, "", { flag: "a" });
1862
2015
  let release;
1863
2016
  try {
1864
2017
  release = await import_proper_lockfile.default.lock(lockPath, {
@@ -1872,26 +2025,26 @@ async function withThreadLock(id, fn) {
1872
2025
  }
1873
2026
  function readThread(id) {
1874
2027
  const path2 = threadFilePath(id);
1875
- if (!(0, import_node_fs7.existsSync)(path2)) return null;
1876
- const raw = (0, import_node_fs7.readFileSync)(path2, "utf8");
2028
+ if (!(0, import_node_fs9.existsSync)(path2)) return null;
2029
+ const raw = (0, import_node_fs9.readFileSync)(path2, "utf8");
1877
2030
  return normalizeThread(JSON.parse(raw));
1878
2031
  }
1879
2032
  function writeThread(thread) {
1880
2033
  const path2 = threadFilePath(idPath(thread.id));
1881
2034
  const tmp = `${path2}.${process.pid}.tmp`;
1882
2035
  const next = { ...thread, updatedAt: nowIso() };
1883
- (0, import_node_fs7.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
1884
- (0, import_node_fs7.renameSync)(tmp, path2);
2036
+ (0, import_node_fs9.writeFileSync)(tmp, JSON.stringify(next, null, 2), "utf8");
2037
+ (0, import_node_fs9.renameSync)(tmp, path2);
1885
2038
  }
1886
2039
  function idPath(id) {
1887
2040
  return id;
1888
2041
  }
1889
2042
  function listThreads(opts) {
1890
- const files = (0, import_node_fs7.readdirSync)(threadsDir()).filter((f) => f.endsWith(".json"));
2043
+ const files = (0, import_node_fs9.readdirSync)(threadsDir()).filter((f) => f.endsWith(".json"));
1891
2044
  const threads = files.map((f) => {
1892
2045
  try {
1893
2046
  return normalizeThread(
1894
- JSON.parse((0, import_node_fs7.readFileSync)(threadFilePath(f.replace(/\.json$/, "")), "utf8"))
2047
+ JSON.parse((0, import_node_fs9.readFileSync)(threadFilePath(f.replace(/\.json$/, "")), "utf8"))
1895
2048
  );
1896
2049
  } catch {
1897
2050
  return null;
@@ -1902,11 +2055,11 @@ function listThreads(opts) {
1902
2055
  }
1903
2056
  function deleteThreadRecord(id) {
1904
2057
  const path2 = threadFilePath(id);
1905
- if ((0, import_node_fs7.existsSync)(path2)) (0, import_node_fs7.unlinkSync)(path2);
2058
+ if ((0, import_node_fs9.existsSync)(path2)) (0, import_node_fs9.unlinkSync)(path2);
1906
2059
  const lock = threadLockPath(id);
1907
- if ((0, import_node_fs7.existsSync)(lock)) {
2060
+ if ((0, import_node_fs9.existsSync)(lock)) {
1908
2061
  try {
1909
- (0, import_node_fs7.unlinkSync)(lock);
2062
+ (0, import_node_fs9.unlinkSync)(lock);
1910
2063
  } catch {
1911
2064
  }
1912
2065
  }
@@ -1930,12 +2083,12 @@ function findThreadByRef(ref) {
1930
2083
  const all = listThreads({ includeArchived: true });
1931
2084
  return all.find((t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref) ?? null;
1932
2085
  }
1933
- var import_node_crypto3, import_node_fs7, import_proper_lockfile;
2086
+ var import_node_crypto3, import_node_fs9, import_proper_lockfile;
1934
2087
  var init_thread_store = __esm({
1935
2088
  "src/store/thread-store.ts"() {
1936
2089
  "use strict";
1937
2090
  import_node_crypto3 = require("crypto");
1938
- import_node_fs7 = require("fs");
2091
+ import_node_fs9 = require("fs");
1939
2092
  import_proper_lockfile = __toESM(require("proper-lockfile"), 1);
1940
2093
  init_thinking_effort();
1941
2094
  init_paths();
@@ -2917,17 +3070,17 @@ var init_gh_errors = __esm({
2917
3070
 
2918
3071
  // src/agents/path.ts
2919
3072
  function prependPathDir(env, dir) {
2920
- if (!dir || !(0, import_node_fs8.existsSync)(dir)) return;
3073
+ if (!dir || !(0, import_node_fs10.existsSync)(dir)) return;
2921
3074
  const current = env.PATH ?? "";
2922
- const parts = current.split(import_node_path8.delimiter).filter(Boolean);
3075
+ const parts = current.split(import_node_path10.delimiter).filter(Boolean);
2923
3076
  if (parts.includes(dir)) {
2924
3077
  env.PATH = current;
2925
3078
  return;
2926
3079
  }
2927
- env.PATH = [dir, ...parts].join(import_node_path8.delimiter);
3080
+ env.PATH = [dir, ...parts].join(import_node_path10.delimiter);
2928
3081
  }
2929
3082
  function conductorBundledBinDir(home = process.env.HOME || process.env.USERPROFILE || (0, import_node_os4.homedir)()) {
2930
- return (0, import_node_path8.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
3083
+ return (0, import_node_path10.join)(home, "Library", "Application Support", "com.conductor.app", "bin");
2931
3084
  }
2932
3085
  function isConductorBundledCli(filePath) {
2933
3086
  const p = (filePath ?? "").replace(/\\/g, "/");
@@ -2936,21 +3089,21 @@ function isConductorBundledCli(filePath) {
2936
3089
  function ensureAgentPath(env = process.env) {
2937
3090
  const home = env.HOME || env.USERPROFILE || (0, import_node_os4.homedir)();
2938
3091
  const current = env.PATH ?? "";
2939
- const parts = current.split(import_node_path8.delimiter).filter(Boolean);
3092
+ const parts = current.split(import_node_path10.delimiter).filter(Boolean);
2940
3093
  const seen = new Set(parts);
2941
3094
  const extras = [
2942
- ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path8.join)(home, rel)),
3095
+ ...EXTRA_BIN_DIRS.map((rel) => (0, import_node_path10.join)(home, rel)),
2943
3096
  "/opt/homebrew/bin",
2944
3097
  "/usr/local/bin",
2945
3098
  // Keep after Homebrew/npm so a user-installed CLI still wins.
2946
3099
  conductorBundledBinDir(home)
2947
3100
  ];
2948
3101
  for (const dir of extras.reverse()) {
2949
- if (!dir || seen.has(dir) || !(0, import_node_fs8.existsSync)(dir)) continue;
3102
+ if (!dir || seen.has(dir) || !(0, import_node_fs10.existsSync)(dir)) continue;
2950
3103
  parts.unshift(dir);
2951
3104
  seen.add(dir);
2952
3105
  }
2953
- const next = parts.join(import_node_path8.delimiter);
3106
+ const next = parts.join(import_node_path10.delimiter);
2954
3107
  env.PATH = next;
2955
3108
  return next;
2956
3109
  }
@@ -2964,7 +3117,7 @@ function enrichPathWithNpmGlobalBin(env = process.env) {
2964
3117
  stdio: ["ignore", "pipe", "ignore"]
2965
3118
  }).trim().split(/\r?\n/).find(Boolean);
2966
3119
  if (prefix) {
2967
- const binDir = process.platform === "win32" ? prefix : (0, import_node_path8.join)(prefix, "bin");
3120
+ const binDir = process.platform === "win32" ? prefix : (0, import_node_path10.join)(prefix, "bin");
2968
3121
  prependPathDir(env, binDir);
2969
3122
  }
2970
3123
  } catch {
@@ -2992,14 +3145,14 @@ function withExportedPath(command, pathValue) {
2992
3145
  if (/^(export\s+PATH=|PATH=)/.test(trimmed)) return trimmed;
2993
3146
  return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
2994
3147
  }
2995
- var import_node_fs8, import_node_child_process3, import_node_os4, import_node_path8, EXTRA_BIN_DIRS;
3148
+ var import_node_fs10, import_node_child_process3, import_node_os4, import_node_path10, EXTRA_BIN_DIRS;
2996
3149
  var init_path = __esm({
2997
3150
  "src/agents/path.ts"() {
2998
3151
  "use strict";
2999
- import_node_fs8 = require("fs");
3152
+ import_node_fs10 = require("fs");
3000
3153
  import_node_child_process3 = require("child_process");
3001
3154
  import_node_os4 = require("os");
3002
- import_node_path8 = require("path");
3155
+ import_node_path10 = require("path");
3003
3156
  EXTRA_BIN_DIRS = [
3004
3157
  ".local/bin",
3005
3158
  ".cargo/bin",
@@ -3027,7 +3180,7 @@ __export(run_exports, {
3027
3180
  async function run(file, args, opts) {
3028
3181
  ensureAgentPath();
3029
3182
  try {
3030
- const result = await (0, import_execa.execa)(file, args, {
3183
+ const result = await (0, import_execa2.execa)(file, args, {
3031
3184
  cwd: opts?.cwd,
3032
3185
  env: { ...process.env, ...opts?.env },
3033
3186
  reject: opts?.reject ?? true,
@@ -3091,11 +3244,11 @@ async function resolveGhAuthToken(cwd) {
3091
3244
  const token = result.stdout.trim();
3092
3245
  return token || null;
3093
3246
  }
3094
- var import_execa;
3247
+ var import_execa2;
3095
3248
  var init_run = __esm({
3096
3249
  "src/git/run.ts"() {
3097
3250
  "use strict";
3098
- import_execa = require("execa");
3251
+ import_execa2 = require("execa");
3099
3252
  init_path();
3100
3253
  }
3101
3254
  });
@@ -4318,8 +4471,8 @@ function isLocalPrFetchBranch(ref) {
4318
4471
  }
4319
4472
  async function createThreadWorktree(opts) {
4320
4473
  let branchName = `thread/${opts.slug}`;
4321
- const worktreePath = (0, import_node_path9.join)(worktreesRoot(opts.repoPath), opts.slug);
4322
- if ((0, import_node_fs9.existsSync)(worktreePath)) {
4474
+ const worktreePath = (0, import_node_path11.join)(worktreesRoot(opts.repoPath), opts.slug);
4475
+ if ((0, import_node_fs11.existsSync)(worktreePath)) {
4323
4476
  throw new Error(`Worktree already exists at ${worktreePath}`);
4324
4477
  }
4325
4478
  await ensureGhPreferOrigin(opts.repoPath);
@@ -4388,8 +4541,8 @@ ${add.stdout}`;
4388
4541
  async function createExistingBranchWorktree(opts) {
4389
4542
  const branchName = opts.branchName.trim();
4390
4543
  if (!branchName) throw new Error("branch name required");
4391
- const worktreePath = (0, import_node_path9.join)(worktreesRoot(opts.repoPath), opts.slug);
4392
- if ((0, import_node_fs9.existsSync)(worktreePath)) {
4544
+ const worktreePath = (0, import_node_path11.join)(worktreesRoot(opts.repoPath), opts.slug);
4545
+ if ((0, import_node_fs11.existsSync)(worktreePath)) {
4393
4546
  throw new Error(`Worktree already exists at ${worktreePath}`);
4394
4547
  }
4395
4548
  await ensureGhPreferOrigin(opts.repoPath);
@@ -4677,10 +4830,10 @@ function sameRepoPath(a, b) {
4677
4830
  return normalizeWorktreePath(a) === normalizeWorktreePath(b);
4678
4831
  }
4679
4832
  function listLocalThreadBranchSlugs(repoPath) {
4680
- const refsDir = (0, import_node_path9.join)(repoPath, ".git", "refs", "heads", "thread");
4681
- if (!(0, import_node_fs9.existsSync)(refsDir)) return [];
4833
+ const refsDir = (0, import_node_path11.join)(repoPath, ".git", "refs", "heads", "thread");
4834
+ if (!(0, import_node_fs11.existsSync)(refsDir)) return [];
4682
4835
  try {
4683
- return (0, import_node_fs9.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
4836
+ return (0, import_node_fs11.readdirSync)(refsDir).filter((name) => !name.startsWith(".")).map((name) => normalizeTakenSlug(name));
4684
4837
  } catch {
4685
4838
  return [];
4686
4839
  }
@@ -4688,8 +4841,8 @@ function listLocalThreadBranchSlugs(repoPath) {
4688
4841
  function collectTakenTeamSlugs(repoPath) {
4689
4842
  const taken = /* @__PURE__ */ new Set();
4690
4843
  const root = worktreesRoot(repoPath);
4691
- if ((0, import_node_fs9.existsSync)(root)) {
4692
- for (const entry of (0, import_node_fs9.readdirSync)(root, { withFileTypes: true })) {
4844
+ if ((0, import_node_fs11.existsSync)(root)) {
4845
+ for (const entry of (0, import_node_fs11.readdirSync)(root, { withFileTypes: true })) {
4693
4846
  if (entry.isDirectory() && entry.name !== ".DS_Store") {
4694
4847
  taken.add(normalizeTakenSlug(entry.name));
4695
4848
  }
@@ -4710,18 +4863,18 @@ function allocateTeamSlug(repoPath) {
4710
4863
  const taken = collectTakenTeamSlugs(repoPath);
4711
4864
  for (let attempt = 0; attempt < 32; attempt++) {
4712
4865
  const team = allocateTeamName(taken);
4713
- const path2 = (0, import_node_path9.join)(worktreesRoot(repoPath), team.slug);
4714
- if (!(0, import_node_fs9.existsSync)(path2)) return team;
4866
+ const path2 = (0, import_node_path11.join)(worktreesRoot(repoPath), team.slug);
4867
+ if (!(0, import_node_fs11.existsSync)(path2)) return team;
4715
4868
  taken.add(team.slug);
4716
4869
  }
4717
4870
  throw new Error("No available soccer team worktree directories left");
4718
4871
  }
4719
- var import_node_fs9, import_node_path9;
4872
+ var import_node_fs11, import_node_path11;
4720
4873
  var init_worktree = __esm({
4721
4874
  "src/git/worktree.ts"() {
4722
4875
  "use strict";
4723
- import_node_fs9 = require("fs");
4724
- import_node_path9 = require("path");
4876
+ import_node_fs11 = require("fs");
4877
+ import_node_path11 = require("path");
4725
4878
  init_paths();
4726
4879
  init_thread_store();
4727
4880
  init_teams();
@@ -4805,7 +4958,7 @@ function coordinatorTurnReminder(opts) {
4805
4958
  function ensureGlobalCoordinatorCwd(opts) {
4806
4959
  const dir = globalAgentCwd();
4807
4960
  try {
4808
- (0, import_node_fs10.mkdirSync)(dir, { recursive: true });
4961
+ (0, import_node_fs12.mkdirSync)(dir, { recursive: true });
4809
4962
  } catch {
4810
4963
  return dir;
4811
4964
  }
@@ -4813,7 +4966,7 @@ function ensureGlobalCoordinatorCwd(opts) {
4813
4966
  let orchId = opts?.orchestratorThreadId?.trim() || "";
4814
4967
  if (!orchId) {
4815
4968
  try {
4816
- const existing = (0, import_node_fs10.readFileSync)((0, import_node_path10.join)(dir, "AGENTS.md"), "utf8");
4969
+ const existing = (0, import_node_fs12.readFileSync)((0, import_node_path12.join)(dir, "AGENTS.md"), "utf8");
4817
4970
  const m = existing.match(
4818
4971
  /YOUR orchestration thread id is `([0-9a-f-]{36})`/i
4819
4972
  );
@@ -4855,9 +5008,9 @@ function ensureGlobalCoordinatorCwd(opts) {
4855
5008
  "Always ask worktree agents to commit, push, and open draft PRs (`ask_git` / `send_to_thread`). Tell them to merge only when the user explicitly asked. The worktree agent runs git/gh; never merge from this orchestration cwd."
4856
5009
  ].join("\n");
4857
5010
  try {
4858
- (0, import_node_fs10.writeFileSync)((0, import_node_path10.join)(dir, "CLAUDE.md"), `${body}
5011
+ (0, import_node_fs12.writeFileSync)((0, import_node_path12.join)(dir, "CLAUDE.md"), `${body}
4859
5012
  `, "utf8");
4860
- (0, import_node_fs10.writeFileSync)((0, import_node_path10.join)(dir, "AGENTS.md"), `${body}
5013
+ (0, import_node_fs12.writeFileSync)((0, import_node_path12.join)(dir, "AGENTS.md"), `${body}
4861
5014
  `, "utf8");
4862
5015
  } catch {
4863
5016
  }
@@ -4889,12 +5042,12 @@ function coordinatorSystemPrompt(opts) {
4889
5042
  formatWorkspaceInventory(opts.workspaces)
4890
5043
  ].join("\n");
4891
5044
  }
4892
- var import_node_fs10, import_node_path10, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
5045
+ var import_node_fs12, import_node_path12, COORDINATOR_TOOL_PLAYBOOK, SLACK_REPLY_FORMATTING;
4893
5046
  var init_coordinator_prompt = __esm({
4894
5047
  "src/orchestrator/coordinator-prompt.ts"() {
4895
5048
  "use strict";
4896
- import_node_fs10 = require("fs");
4897
- import_node_path10 = require("path");
5049
+ import_node_fs12 = require("fs");
5050
+ import_node_path12 = require("path");
4898
5051
  init_worktree();
4899
5052
  init_app_settings();
4900
5053
  init_paths();
@@ -4915,7 +5068,7 @@ var init_coordinator_prompt = __esm({
4915
5068
  "Workspaces:",
4916
5069
  "- add_workspace / remove_workspace \u2014 register or unregister a git repo",
4917
5070
  "Worktree threads (chats):",
4918
- "- create_thread \u2014 create a worktree + chat from branch | pr | ticket; pass repoPath + parentThreadId; omit agent and model to use Sideboard Account defaults (Settings \u2192 Default agent, model & effort). If you are Codex, do not set agent=codex (nested Codex deadlocks)",
5071
+ "- create_thread \u2014 create a worktree + chat from branch | pr | ticket; pass repoPath + parentThreadId; omit agent and model to use Sideboard Account defaults (Settings \u2192 Default agent, model & effort). If the repo has a setup script, Sideboard runs it in the background (does not block send_to_thread). If you are Codex, do not set agent=codex (nested Codex deadlocks)",
4919
5072
  "- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
4920
5073
  "- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
4921
5074
  "- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
@@ -4923,7 +5076,7 @@ var init_coordinator_prompt = __esm({
4923
5076
  "- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
4924
5077
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
4925
5078
  "Setup / run:",
4926
- "- run_setup \u2014 re-run worktree setup",
5079
+ "- run_setup \u2014 re-run worktree setup (already runs automatically on create when a script exists)",
4927
5080
  "- list_run_scripts / run_dev_script / stop_dev_script \u2014 start/stop named run scripts",
4928
5081
  "Inspect / review / PRs:",
4929
5082
  "- get_diff \u2014 compact diff summary",
@@ -5200,38 +5353,38 @@ __export(workspaces_exports, {
5200
5353
  syncWorkspacesFromThreads: () => syncWorkspacesFromThreads
5201
5354
  });
5202
5355
  function workspacesFile() {
5203
- return (0, import_node_path11.join)(appDataDir(), "workspaces.json");
5356
+ return (0, import_node_path13.join)(appDataDir(), "workspaces.json");
5204
5357
  }
5205
5358
  function removedWorkspacesFile() {
5206
- return (0, import_node_path11.join)(appDataDir(), "removed-workspaces.json");
5359
+ return (0, import_node_path13.join)(appDataDir(), "removed-workspaces.json");
5207
5360
  }
5208
5361
  function readAll() {
5209
5362
  const path2 = workspacesFile();
5210
- if (!(0, import_node_fs11.existsSync)(path2)) return [];
5363
+ if (!(0, import_node_fs13.existsSync)(path2)) return [];
5211
5364
  try {
5212
- const raw = JSON.parse((0, import_node_fs11.readFileSync)(path2, "utf8"));
5365
+ const raw = JSON.parse((0, import_node_fs13.readFileSync)(path2, "utf8"));
5213
5366
  return Array.isArray(raw) ? raw : [];
5214
5367
  } catch {
5215
5368
  return [];
5216
5369
  }
5217
5370
  }
5218
5371
  function writeAll(list) {
5219
- (0, import_node_fs11.mkdirSync)(appDataDir(), { recursive: true });
5220
- (0, import_node_fs11.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
5372
+ (0, import_node_fs13.mkdirSync)(appDataDir(), { recursive: true });
5373
+ (0, import_node_fs13.writeFileSync)(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
5221
5374
  }
5222
5375
  function readRemoved() {
5223
5376
  const path2 = removedWorkspacesFile();
5224
- if (!(0, import_node_fs11.existsSync)(path2)) return /* @__PURE__ */ new Set();
5377
+ if (!(0, import_node_fs13.existsSync)(path2)) return /* @__PURE__ */ new Set();
5225
5378
  try {
5226
- const raw = JSON.parse((0, import_node_fs11.readFileSync)(path2, "utf8"));
5379
+ const raw = JSON.parse((0, import_node_fs13.readFileSync)(path2, "utf8"));
5227
5380
  return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
5228
5381
  } catch {
5229
5382
  return /* @__PURE__ */ new Set();
5230
5383
  }
5231
5384
  }
5232
5385
  function writeRemoved(paths) {
5233
- (0, import_node_fs11.mkdirSync)(appDataDir(), { recursive: true });
5234
- (0, import_node_fs11.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
5386
+ (0, import_node_fs13.mkdirSync)(appDataDir(), { recursive: true });
5387
+ (0, import_node_fs13.writeFileSync)(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
5235
5388
  }
5236
5389
  function rememberRemoved(repoPath) {
5237
5390
  const next = readRemoved();
@@ -5254,7 +5407,7 @@ function listWorkspaces() {
5254
5407
  async function addWorkspace(repoPath) {
5255
5408
  const root = await resolveRepoRoot(repoPath);
5256
5409
  if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
5257
- if (!(0, import_node_fs11.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
5410
+ if (!(0, import_node_fs13.existsSync)(root)) throw new Error(`Repo not found: ${root}`);
5258
5411
  forgetRemoved(root);
5259
5412
  await ensureGhPreferOrigin(root);
5260
5413
  const current = readAll();
@@ -5262,7 +5415,7 @@ async function addWorkspace(repoPath) {
5262
5415
  if (existing) return existing;
5263
5416
  const next = {
5264
5417
  path: root,
5265
- name: (0, import_node_path11.basename)(root),
5418
+ name: (0, import_node_path13.basename)(root),
5266
5419
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
5267
5420
  };
5268
5421
  writeAll([...current, next]);
@@ -5284,10 +5437,10 @@ function syncWorkspacesFromThreads(repoPaths) {
5284
5437
  if (!path2 || path2 === "/" || isGlobalRepoPath(path2) || byPath.has(path2) || removed.has(path2)) {
5285
5438
  continue;
5286
5439
  }
5287
- if (!(0, import_node_fs11.existsSync)(path2)) continue;
5440
+ if (!(0, import_node_fs13.existsSync)(path2)) continue;
5288
5441
  const ws = {
5289
5442
  path: path2,
5290
- name: (0, import_node_path11.basename)(path2),
5443
+ name: (0, import_node_path13.basename)(path2),
5291
5444
  addedAt: (/* @__PURE__ */ new Date()).toISOString()
5292
5445
  };
5293
5446
  byPath.set(path2, ws);
@@ -5297,12 +5450,12 @@ function syncWorkspacesFromThreads(repoPaths) {
5297
5450
  if (dirty) writeAll(next);
5298
5451
  return next.sort((a, b) => a.name.localeCompare(b.name));
5299
5452
  }
5300
- var import_node_fs11, import_node_path11;
5453
+ var import_node_fs13, import_node_path13;
5301
5454
  var init_workspaces = __esm({
5302
5455
  "src/store/workspaces.ts"() {
5303
5456
  "use strict";
5304
- import_node_fs11 = require("fs");
5305
- import_node_path11 = require("path");
5457
+ import_node_fs13 = require("fs");
5458
+ import_node_path13 = require("path");
5306
5459
  init_paths();
5307
5460
  init_global_workspace();
5308
5461
  init_worktree();
@@ -5311,32 +5464,32 @@ var init_workspaces = __esm({
5311
5464
 
5312
5465
  // src/brightsy/config.ts
5313
5466
  function brightsyConfigPath() {
5314
- return (0, import_node_path12.join)((0, import_node_os5.homedir)(), ".brightsy", "config.json");
5467
+ return (0, import_node_path14.join)((0, import_node_os5.homedir)(), ".brightsy", "config.json");
5315
5468
  }
5316
5469
  function loadBrightsyConfig() {
5317
5470
  const path2 = brightsyConfigPath();
5318
- if (!(0, import_node_fs12.existsSync)(path2)) {
5471
+ if (!(0, import_node_fs14.existsSync)(path2)) {
5319
5472
  throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
5320
5473
  }
5321
- const raw = JSON.parse((0, import_node_fs12.readFileSync)(path2, "utf8"));
5474
+ const raw = JSON.parse((0, import_node_fs14.readFileSync)(path2, "utf8"));
5322
5475
  if (!raw.access_token || !raw.account_id) {
5323
5476
  throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
5324
5477
  }
5325
5478
  return raw;
5326
5479
  }
5327
5480
  function saveBrightsyConfig(cfg) {
5328
- (0, import_node_fs12.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
5481
+ (0, import_node_fs14.writeFileSync)(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
5329
5482
  `, {
5330
5483
  mode: 384
5331
5484
  });
5332
5485
  }
5333
- var import_node_fs12, import_node_os5, import_node_path12;
5486
+ var import_node_fs14, import_node_os5, import_node_path14;
5334
5487
  var init_config = __esm({
5335
5488
  "src/brightsy/config.ts"() {
5336
5489
  "use strict";
5337
- import_node_fs12 = require("fs");
5490
+ import_node_fs14 = require("fs");
5338
5491
  import_node_os5 = require("os");
5339
- import_node_path12 = require("path");
5492
+ import_node_path14 = require("path");
5340
5493
  }
5341
5494
  });
5342
5495
 
@@ -5439,22 +5592,22 @@ __export(connected_teams_exports, {
5439
5592
  listConnectedBrightsyTeams: () => listConnectedBrightsyTeams
5440
5593
  });
5441
5594
  function storePath() {
5442
- return (0, import_node_path13.join)(appDataDir(), "brightsy-teams.json");
5595
+ return (0, import_node_path15.join)(appDataDir(), "brightsy-teams.json");
5443
5596
  }
5444
5597
  function readStore() {
5445
5598
  const path2 = storePath();
5446
- if (!(0, import_node_fs13.existsSync)(path2)) return [];
5599
+ if (!(0, import_node_fs15.existsSync)(path2)) return [];
5447
5600
  try {
5448
- const parsed = JSON.parse((0, import_node_fs13.readFileSync)(path2, "utf8"));
5601
+ const parsed = JSON.parse((0, import_node_fs15.readFileSync)(path2, "utf8"));
5449
5602
  return Array.isArray(parsed.teams) ? parsed.teams : [];
5450
5603
  } catch {
5451
5604
  return [];
5452
5605
  }
5453
5606
  }
5454
5607
  function writeStore(teams) {
5455
- (0, import_node_fs13.mkdirSync)(appDataDir(), { recursive: true });
5608
+ (0, import_node_fs15.mkdirSync)(appDataDir(), { recursive: true });
5456
5609
  const path2 = storePath();
5457
- (0, import_node_fs13.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
5610
+ (0, import_node_fs15.writeFileSync)(path2, `${JSON.stringify({ teams }, null, 2)}
5458
5611
  `, {
5459
5612
  mode: 384
5460
5613
  });
@@ -5616,12 +5769,12 @@ function brightsyMcpServerName(slug) {
5616
5769
  const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
5617
5770
  return `brightsy_${cleaned || "team"}`;
5618
5771
  }
5619
- var import_node_fs13, import_node_path13;
5772
+ var import_node_fs15, import_node_path15;
5620
5773
  var init_connected_teams = __esm({
5621
5774
  "src/brightsy/connected-teams.ts"() {
5622
5775
  "use strict";
5623
- import_node_fs13 = require("fs");
5624
- import_node_path13 = require("path");
5776
+ import_node_fs15 = require("fs");
5777
+ import_node_path15 = require("path");
5625
5778
  init_paths();
5626
5779
  init_accounts();
5627
5780
  init_config();
@@ -6150,11 +6303,11 @@ async function syncCliForTarget(accountId) {
6150
6303
  }
6151
6304
  applyConnectedTeamToCli(team);
6152
6305
  }
6153
- var import_node_fs14, brightsyAdapter;
6306
+ var import_node_fs16, brightsyAdapter;
6154
6307
  var init_brightsy = __esm({
6155
6308
  "src/agents/brightsy.ts"() {
6156
6309
  "use strict";
6157
- import_node_fs14 = require("fs");
6310
+ import_node_fs16 = require("fs");
6158
6311
  init_run();
6159
6312
  init_connected_teams();
6160
6313
  init_config();
@@ -6169,7 +6322,7 @@ var init_brightsy = __esm({
6169
6322
  async detect() {
6170
6323
  const brightsy = resolveAgentExecutable("brightsy");
6171
6324
  if (brightsy !== "brightsy") {
6172
- if (!(0, import_node_fs14.existsSync)(brightsy)) {
6325
+ if (!(0, import_node_fs16.existsSync)(brightsy)) {
6173
6326
  return {
6174
6327
  agent: "brightsy",
6175
6328
  installed: false,
@@ -6426,35 +6579,35 @@ function corePackageDir() {
6426
6579
  try {
6427
6580
  const url = import_meta.url;
6428
6581
  if (typeof url === "string" && url.length > 0) {
6429
- return (0, import_node_path14.dirname)((0, import_node_url.fileURLToPath)(url));
6582
+ return (0, import_node_path16.dirname)((0, import_node_url.fileURLToPath)(url));
6430
6583
  }
6431
6584
  } catch {
6432
6585
  }
6433
6586
  try {
6434
- const req = (0, import_node_module.createRequire)((0, import_node_path14.join)(process.cwd(), "package.json"));
6435
- return (0, import_node_path14.dirname)(req.resolve("@sideboard-ai/core"));
6587
+ const req = (0, import_node_module.createRequire)((0, import_node_path16.join)(process.cwd(), "package.json"));
6588
+ return (0, import_node_path16.dirname)(req.resolve("@sideboard-ai/core"));
6436
6589
  } catch {
6437
6590
  return process.cwd();
6438
6591
  }
6439
6592
  }
6440
6593
  function findSideboardMcpJsEntry() {
6441
6594
  const override = process.env.SIDEBOARD_MCP_ENTRY?.trim() || process.env.SIDEBOARD_CLI?.trim();
6442
- if (override && (0, import_node_fs15.existsSync)(override)) return override;
6595
+ if (override && (0, import_node_fs17.existsSync)(override)) return override;
6443
6596
  let dir = corePackageDir();
6444
6597
  for (let i = 0; i < 10; i++) {
6445
6598
  const candidates = [
6446
- (0, import_node_path14.join)(dir, "mcp/run-stdio.js"),
6447
- (0, import_node_path14.join)(dir, "mcp/run-stdio.cjs"),
6448
- (0, import_node_path14.join)(dir, "dist/mcp/run-stdio.js"),
6449
- (0, import_node_path14.join)(dir, "dist/mcp/run-stdio.cjs"),
6450
- (0, import_node_path14.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
6451
- (0, import_node_path14.join)(dir, "packages/cli/dist/index.js"),
6452
- (0, import_node_path14.join)(dir, "cli/dist/index.js")
6599
+ (0, import_node_path16.join)(dir, "mcp/run-stdio.js"),
6600
+ (0, import_node_path16.join)(dir, "mcp/run-stdio.cjs"),
6601
+ (0, import_node_path16.join)(dir, "dist/mcp/run-stdio.js"),
6602
+ (0, import_node_path16.join)(dir, "dist/mcp/run-stdio.cjs"),
6603
+ (0, import_node_path16.join)(dir, "packages/core/dist/mcp/run-stdio.js"),
6604
+ (0, import_node_path16.join)(dir, "packages/cli/dist/index.js"),
6605
+ (0, import_node_path16.join)(dir, "cli/dist/index.js")
6453
6606
  ];
6454
6607
  for (const p of candidates) {
6455
- if ((0, import_node_fs15.existsSync)(p)) return p;
6608
+ if ((0, import_node_fs17.existsSync)(p)) return p;
6456
6609
  }
6457
- const parent = (0, import_node_path14.dirname)(dir);
6610
+ const parent = (0, import_node_path16.dirname)(dir);
6458
6611
  if (parent === dir) break;
6459
6612
  dir = parent;
6460
6613
  }
@@ -6516,22 +6669,52 @@ async function buildInjectedMcpServers(opts) {
6516
6669
  }
6517
6670
  return servers;
6518
6671
  }
6672
+ function shSingleQuote(value) {
6673
+ return `'${value.replace(/'/g, `'\\''`)}'`;
6674
+ }
6675
+ function cursorSafeMcpLaunch(command, args) {
6676
+ if (process.platform === "win32") {
6677
+ return args && args.length > 0 ? { command, args } : { command };
6678
+ }
6679
+ const unwrapped = unwrapStrippedElectronLaunch(command, args);
6680
+ const file = unwrapped?.file ?? command;
6681
+ const fileArgs = unwrapped?.args ?? args ?? [];
6682
+ if (!isElectronLikeCommand(file)) {
6683
+ return fileArgs.length > 0 ? { command: file, args: fileArgs } : { command: file };
6684
+ }
6685
+ const dir = (0, import_node_path16.join)(appDataDir(), "mcp-launch");
6686
+ (0, import_node_fs17.mkdirSync)(dir, { recursive: true });
6687
+ const wrap = (0, import_node_path16.join)(dir, "cursor-electron-as-node.sh");
6688
+ const execLine = [file, ...fileArgs].map(shSingleQuote).join(" ");
6689
+ (0, import_node_fs17.writeFileSync)(
6690
+ wrap,
6691
+ [
6692
+ "#!/bin/sh",
6693
+ "vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
6694
+ '[ -n "$vars" ] && unset $vars',
6695
+ "export ELECTRON_RUN_AS_NODE=1",
6696
+ `exec ${execLine} "$@"`,
6697
+ ""
6698
+ ].join("\n"),
6699
+ { mode: 493 }
6700
+ );
6701
+ return { command: wrap };
6702
+ }
6703
+ function mcpSpawnEnv(env) {
6704
+ if (!env) return void 0;
6705
+ const out = { ...env };
6706
+ delete out.ELECTRON_RUN_AS_NODE;
6707
+ return Object.keys(out).length > 0 ? out : void 0;
6708
+ }
6519
6709
  function toCursorMcpServers(servers) {
6520
6710
  const out = {};
6521
6711
  for (const s of servers) {
6522
- const env = s.env ? { ...s.env } : void 0;
6523
- if (env) delete env.ELECTRON_RUN_AS_NODE;
6524
- let command = s.command;
6525
- let args = s.args;
6526
- if (process.platform !== "win32" && !isStrippedElectronLaunch(command, args)) {
6527
- const wrapped = wrapElectronAsNodeLaunch(command, args ?? []);
6528
- command = wrapped.file;
6529
- args = wrapped.args;
6530
- }
6712
+ const env = mcpSpawnEnv(s.env);
6713
+ const launch = cursorSafeMcpLaunch(s.command, s.args);
6531
6714
  out[s.name] = {
6532
- command,
6533
- ...args && args.length > 0 ? { args } : {},
6534
- ...env && Object.keys(env).length > 0 ? { env } : {}
6715
+ command: launch.command,
6716
+ ...launch.args && launch.args.length > 0 ? { args: launch.args } : {},
6717
+ ...env ? { env } : {}
6535
6718
  };
6536
6719
  }
6537
6720
  return out;
@@ -6544,8 +6727,9 @@ function toCodexMcpConfigArgs(servers) {
6544
6727
  if (s.args?.length) {
6545
6728
  args.push("-c", `${prefix}.args=${JSON.stringify(s.args)}`);
6546
6729
  }
6547
- if (s.env) {
6548
- for (const [key, value] of Object.entries(s.env)) {
6730
+ const env = mcpSpawnEnv(s.env);
6731
+ if (env) {
6732
+ for (const [key, value] of Object.entries(env)) {
6549
6733
  args.push("-c", `${prefix}.env.${key}=${JSON.stringify(value)}`);
6550
6734
  }
6551
6735
  }
@@ -6558,11 +6742,12 @@ function toCodexMcpConfigArgs(servers) {
6558
6742
  function toOpencodeMcpConfigContent(servers) {
6559
6743
  const mcp = {};
6560
6744
  for (const s of servers) {
6745
+ const env = mcpSpawnEnv(s.env);
6561
6746
  mcp[s.name] = {
6562
6747
  type: "local",
6563
6748
  command: [s.command, ...s.args ?? []],
6564
6749
  enabled: true,
6565
- ...s.env && Object.keys(s.env).length > 0 ? { environment: s.env } : {}
6750
+ ...env ? { environment: env } : {}
6566
6751
  };
6567
6752
  }
6568
6753
  return JSON.stringify({ mcp });
@@ -6571,28 +6756,29 @@ function writeMcpServersConfig(servers) {
6571
6756
  if (servers.length === 0) return null;
6572
6757
  const mcpServers = {};
6573
6758
  for (const s of servers) {
6759
+ const env = mcpSpawnEnv(s.env);
6574
6760
  mcpServers[s.name] = {
6575
6761
  command: s.command,
6576
6762
  ...s.args ? { args: s.args } : {},
6577
- ...s.env ? { env: s.env } : {}
6763
+ ...env ? { env } : {}
6578
6764
  };
6579
6765
  }
6580
- const dir = (0, import_node_fs15.mkdtempSync)((0, import_node_path14.join)((0, import_node_os6.tmpdir)(), "sideboard-mcp-"));
6581
- const cfgPath = (0, import_node_path14.join)(dir, "mcp.json");
6582
- (0, import_node_fs15.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
6766
+ const dir = (0, import_node_fs17.mkdtempSync)((0, import_node_path16.join)((0, import_node_os6.tmpdir)(), "sideboard-mcp-"));
6767
+ const cfgPath = (0, import_node_path16.join)(dir, "mcp.json");
6768
+ (0, import_node_fs17.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
6583
6769
  return cfgPath;
6584
6770
  }
6585
6771
  async function writeInjectedMcpConfig(opts) {
6586
6772
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
6587
6773
  }
6588
- var import_node_fs15, import_node_module, import_node_os6, import_node_path14, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
6774
+ var import_node_fs17, import_node_module, import_node_os6, import_node_path16, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache, BRIGHTSY_WORD;
6589
6775
  var init_injected_mcp = __esm({
6590
6776
  "src/agents/injected-mcp.ts"() {
6591
6777
  "use strict";
6592
- import_node_fs15 = require("fs");
6778
+ import_node_fs17 = require("fs");
6593
6779
  import_node_module = require("module");
6594
6780
  import_node_os6 = require("os");
6595
- import_node_path14 = require("path");
6781
+ import_node_path16 = require("path");
6596
6782
  import_node_url = require("url");
6597
6783
  init_run();
6598
6784
  init_config();
@@ -6784,11 +6970,11 @@ function parseIssuesJson(raw) {
6784
6970
  }
6785
6971
  return [];
6786
6972
  }
6787
- var import_node_fs16, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
6973
+ var import_node_fs18, BASE_ALLOWED_TOOLS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
6788
6974
  var init_claude = __esm({
6789
6975
  "src/agents/claude.ts"() {
6790
6976
  "use strict";
6791
- import_node_fs16 = require("fs");
6977
+ import_node_fs18 = require("fs");
6792
6978
  init_run();
6793
6979
  init_app_settings();
6794
6980
  init_claude_mcp();
@@ -6817,7 +7003,7 @@ var init_claude = __esm({
6817
7003
  async detect() {
6818
7004
  const claude = resolveClaudeExecutable();
6819
7005
  if (claude !== "claude") {
6820
- if (!(0, import_node_fs16.existsSync)(claude)) {
7006
+ if (!(0, import_node_fs18.existsSync)(claude)) {
6821
7007
  return {
6822
7008
  agent: "claude",
6823
7009
  installed: false,
@@ -7054,7 +7240,7 @@ async function listCodexModels() {
7054
7240
  if (codex === "codex") {
7055
7241
  const which = await run("which", ["codex"], { reject: false });
7056
7242
  if (which.exitCode !== 0) return FALLBACK_CODEX_MODELS;
7057
- } else if (!(0, import_node_fs17.existsSync)(codex)) {
7243
+ } else if (!(0, import_node_fs19.existsSync)(codex)) {
7058
7244
  return FALLBACK_CODEX_MODELS;
7059
7245
  }
7060
7246
  const listed = await run(codex, ["debug", "models"], { reject: false });
@@ -7089,12 +7275,12 @@ function usageFromCodex(usage) {
7089
7275
  }
7090
7276
  function codexConfigHasNetworkAccess() {
7091
7277
  const candidates = [
7092
- (0, import_node_path15.join)((0, import_node_os7.homedir)(), ".codex", "config.toml"),
7093
- (0, import_node_path15.join)((0, import_node_os7.homedir)(), ".config", "codex", "config.toml")
7278
+ (0, import_node_path17.join)((0, import_node_os7.homedir)(), ".codex", "config.toml"),
7279
+ (0, import_node_path17.join)((0, import_node_os7.homedir)(), ".config", "codex", "config.toml")
7094
7280
  ];
7095
7281
  for (const path2 of candidates) {
7096
- if (!(0, import_node_fs17.existsSync)(path2)) continue;
7097
- const text3 = (0, import_node_fs17.readFileSync)(path2, "utf8");
7282
+ if (!(0, import_node_fs19.existsSync)(path2)) continue;
7283
+ const text3 = (0, import_node_fs19.readFileSync)(path2, "utf8");
7098
7284
  if (/network_access\s*=\s*true/.test(text3)) return true;
7099
7285
  }
7100
7286
  return false;
@@ -7126,21 +7312,21 @@ function asRecord(value) {
7126
7312
  return void 0;
7127
7313
  }
7128
7314
  function codexLooksAuthenticated() {
7129
- const authPath = (0, import_node_path15.join)((0, import_node_os7.homedir)(), ".codex", "auth.json");
7130
- if (!(0, import_node_fs17.existsSync)(authPath)) return false;
7315
+ const authPath = (0, import_node_path17.join)((0, import_node_os7.homedir)(), ".codex", "auth.json");
7316
+ if (!(0, import_node_fs19.existsSync)(authPath)) return false;
7131
7317
  try {
7132
- return (0, import_node_fs17.statSync)(authPath).size > 2;
7318
+ return (0, import_node_fs19.statSync)(authPath).size > 2;
7133
7319
  } catch {
7134
7320
  return false;
7135
7321
  }
7136
7322
  }
7137
- var import_node_fs17, import_node_os7, import_node_path15, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
7323
+ var import_node_fs19, import_node_os7, import_node_path17, CODEX_PROMPT_ARG_MAX, FALLBACK_CODEX_MODELS, cachedCodexModels, CODEX_MODEL_CACHE_MS, codexAdapter;
7138
7324
  var init_codex = __esm({
7139
7325
  "src/agents/codex.ts"() {
7140
7326
  "use strict";
7141
- import_node_fs17 = require("fs");
7327
+ import_node_fs19 = require("fs");
7142
7328
  import_node_os7 = require("os");
7143
- import_node_path15 = require("path");
7329
+ import_node_path17 = require("path");
7144
7330
  init_run();
7145
7331
  init_app_settings();
7146
7332
  init_global_workspace();
@@ -7165,7 +7351,7 @@ var init_codex = __esm({
7165
7351
  async detect() {
7166
7352
  const codex = resolveAgentExecutable("codex");
7167
7353
  if (codex !== "codex") {
7168
- if (!(0, import_node_fs17.existsSync)(codex)) {
7354
+ if (!(0, import_node_fs19.existsSync)(codex)) {
7169
7355
  return {
7170
7356
  agent: "codex",
7171
7357
  installed: false,
@@ -7599,11 +7785,11 @@ function entryDir() {
7599
7785
  const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
7600
7786
  if (cjsDir) return cjsDir;
7601
7787
  try {
7602
- return (0, import_node_path16.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
7788
+ return (0, import_node_path18.dirname)((0, import_node_url2.fileURLToPath)(import_meta2.url));
7603
7789
  } catch {
7604
7790
  try {
7605
7791
  const req = (0, import_node_module2.createRequire)(process.cwd() + "/");
7606
- return (0, import_node_path16.dirname)(req.resolve("@sideboard-ai/core"));
7792
+ return (0, import_node_path18.dirname)(req.resolve("@sideboard-ai/core"));
7607
7793
  } catch {
7608
7794
  return process.cwd();
7609
7795
  }
@@ -7612,27 +7798,27 @@ function entryDir() {
7612
7798
  function cursorRunnerPath() {
7613
7799
  const root = entryDir();
7614
7800
  const candidates = [
7615
- (0, import_node_path16.join)(root, "agents", "cursor-runner.js"),
7616
- (0, import_node_path16.join)(root, "agents", "cursor-runner.cjs"),
7801
+ (0, import_node_path18.join)(root, "agents", "cursor-runner.js"),
7802
+ (0, import_node_path18.join)(root, "agents", "cursor-runner.cjs"),
7617
7803
  // If somehow resolved from package root instead of dist/
7618
- (0, import_node_path16.join)(root, "dist", "agents", "cursor-runner.js"),
7619
- (0, import_node_path16.join)(root, "dist", "agents", "cursor-runner.cjs"),
7804
+ (0, import_node_path18.join)(root, "dist", "agents", "cursor-runner.js"),
7805
+ (0, import_node_path18.join)(root, "dist", "agents", "cursor-runner.cjs"),
7620
7806
  // Source tree (dev): packages/core/src/agents/cursor-runner.ts
7621
- (0, import_node_path16.join)(root, "cursor-runner.ts"),
7622
- (0, import_node_path16.join)(root, "src", "agents", "cursor-runner.ts")
7807
+ (0, import_node_path18.join)(root, "cursor-runner.ts"),
7808
+ (0, import_node_path18.join)(root, "src", "agents", "cursor-runner.ts")
7623
7809
  ];
7624
7810
  for (const candidate of candidates) {
7625
- if ((0, import_node_fs18.existsSync)(candidate)) return candidate;
7811
+ if ((0, import_node_fs20.existsSync)(candidate)) return candidate;
7626
7812
  }
7627
7813
  return candidates[0];
7628
7814
  }
7629
- var import_node_fs18, import_node_module2, import_node_path16, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
7815
+ var import_node_fs20, import_node_module2, import_node_path18, import_node_url2, import_sdk, import_meta2, FALLBACK_CURSOR_MODELS, cachedModels, MODEL_CACHE_MS, cursorAdapter;
7630
7816
  var init_cursor = __esm({
7631
7817
  "src/agents/cursor.ts"() {
7632
7818
  "use strict";
7633
- import_node_fs18 = require("fs");
7819
+ import_node_fs20 = require("fs");
7634
7820
  import_node_module2 = require("module");
7635
- import_node_path16 = require("path");
7821
+ import_node_path18 = require("path");
7636
7822
  import_node_url2 = require("url");
7637
7823
  import_sdk = require("@cursor/sdk");
7638
7824
  init_run();
@@ -7761,7 +7947,7 @@ async function listOpencodeModels() {
7761
7947
  if (opencode === "opencode") {
7762
7948
  const which = await run("which", ["opencode"], { reject: false });
7763
7949
  if (which.exitCode !== 0) return FALLBACK_OPENCODE_MODELS;
7764
- } else if (!(0, import_node_fs19.existsSync)(opencode)) {
7950
+ } else if (!(0, import_node_fs21.existsSync)(opencode)) {
7765
7951
  return FALLBACK_OPENCODE_MODELS;
7766
7952
  }
7767
7953
  const listed = await run(opencode, ["models"], { reject: false });
@@ -7791,11 +7977,11 @@ function usageFromOpencode(tokens) {
7791
7977
  cacheWriteTokens: tokens.cache?.write ? Number(tokens.cache.write) : void 0
7792
7978
  };
7793
7979
  }
7794
- var import_node_fs19, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
7980
+ var import_node_fs21, FALLBACK_OPENCODE_MODELS, cachedOpencodeModels, OPENCODE_MODEL_CACHE_MS, opencodeAdapter;
7795
7981
  var init_opencode = __esm({
7796
7982
  "src/agents/opencode.ts"() {
7797
7983
  "use strict";
7798
- import_node_fs19 = require("fs");
7984
+ import_node_fs21 = require("fs");
7799
7985
  init_run();
7800
7986
  init_app_settings();
7801
7987
  init_global_workspace();
@@ -7821,7 +8007,7 @@ var init_opencode = __esm({
7821
8007
  async detect() {
7822
8008
  const opencode = resolveAgentExecutable("opencode");
7823
8009
  if (opencode !== "opencode") {
7824
- if (!(0, import_node_fs19.existsSync)(opencode)) {
8010
+ if (!(0, import_node_fs21.existsSync)(opencode)) {
7825
8011
  return {
7826
8012
  agent: "opencode",
7827
8013
  installed: false,
@@ -8618,40 +8804,40 @@ __export(plan_file_exports, {
8618
8804
  writePlanFile: () => writePlanFile
8619
8805
  });
8620
8806
  function ensureAttachmentsGitignore2(worktreePath) {
8621
- const gitignoreAbs = (0, import_node_path30.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
8622
- if ((0, import_node_fs34.existsSync)(gitignoreAbs)) return;
8623
- (0, import_node_fs34.mkdirSync)((0, import_node_path30.dirname)(gitignoreAbs), { recursive: true });
8624
- (0, import_node_fs34.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
8807
+ const gitignoreAbs = (0, import_node_path31.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
8808
+ if ((0, import_node_fs35.existsSync)(gitignoreAbs)) return;
8809
+ (0, import_node_fs35.mkdirSync)((0, import_node_path31.dirname)(gitignoreAbs), { recursive: true });
8810
+ (0, import_node_fs35.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
8625
8811
  }
8626
8812
  function planFileAbs(worktreePath) {
8627
- return (0, import_node_path30.join)(worktreePath, PLAN_FILE_REL);
8813
+ return (0, import_node_path31.join)(worktreePath, PLAN_FILE_REL);
8628
8814
  }
8629
8815
  function readTextIfPresent2(abs) {
8630
- if (!(0, import_node_fs34.existsSync)(abs)) return null;
8816
+ if (!(0, import_node_fs35.existsSync)(abs)) return null;
8631
8817
  try {
8632
- const content = (0, import_node_fs34.readFileSync)(abs, "utf8");
8818
+ const content = (0, import_node_fs35.readFileSync)(abs, "utf8");
8633
8819
  return content.trim() ? content : null;
8634
8820
  } catch {
8635
8821
  return null;
8636
8822
  }
8637
8823
  }
8638
8824
  function readPlanFile(worktreePath) {
8639
- return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path30.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path30.join)(worktreePath, LEGACY_PLAN_FILE_REL));
8825
+ return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path31.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path31.join)(worktreePath, LEGACY_PLAN_FILE_REL));
8640
8826
  }
8641
8827
  function writePlanFile(worktreePath, content) {
8642
8828
  ensureAttachmentsGitignore2(worktreePath);
8643
8829
  const abs = planFileAbs(worktreePath);
8644
- (0, import_node_fs34.mkdirSync)((0, import_node_path30.dirname)(abs), { recursive: true });
8830
+ (0, import_node_fs35.mkdirSync)((0, import_node_path31.dirname)(abs), { recursive: true });
8645
8831
  const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
8646
- (0, import_node_fs34.writeFileSync)(abs, body, "utf8");
8832
+ (0, import_node_fs35.writeFileSync)(abs, body, "utf8");
8647
8833
  return PLAN_FILE_REL;
8648
8834
  }
8649
- var import_node_fs34, import_node_path30;
8835
+ var import_node_fs35, import_node_path31;
8650
8836
  var init_plan_file = __esm({
8651
8837
  "src/plan/plan-file.ts"() {
8652
8838
  "use strict";
8653
- import_node_fs34 = require("fs");
8654
- import_node_path30 = require("path");
8839
+ import_node_fs35 = require("fs");
8840
+ import_node_path31 = require("path");
8655
8841
  init_workspace_scratch();
8656
8842
  init_plan_present();
8657
8843
  init_plan_present();
@@ -8666,10 +8852,10 @@ __export(cursor_recover_exports, {
8666
8852
  function recoverFinishedCursorRun(opts) {
8667
8853
  const agentId = opts.agentId.trim();
8668
8854
  if (!agentId) return null;
8669
- const runsPath = (0, import_node_path31.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
8670
- if (!(0, import_node_fs35.existsSync)(runsPath)) return null;
8855
+ const runsPath = (0, import_node_path32.join)(appDataDir(), "cursor-sdk-store", "runs.ndjson");
8856
+ if (!(0, import_node_fs36.existsSync)(runsPath)) return null;
8671
8857
  try {
8672
- const lines = (0, import_node_fs35.readFileSync)(runsPath, "utf8").split("\n");
8858
+ const lines = (0, import_node_fs36.readFileSync)(runsPath, "utf8").split("\n");
8673
8859
  let best = null;
8674
8860
  for (const line of lines) {
8675
8861
  const trimmed = line.trim();
@@ -8695,12 +8881,12 @@ function recoverFinishedCursorRun(opts) {
8695
8881
  return null;
8696
8882
  }
8697
8883
  }
8698
- var import_node_fs35, import_node_path31;
8884
+ var import_node_fs36, import_node_path32;
8699
8885
  var init_cursor_recover = __esm({
8700
8886
  "src/agents/cursor-recover.ts"() {
8701
8887
  "use strict";
8702
- import_node_fs35 = require("fs");
8703
- import_node_path31 = require("path");
8888
+ import_node_fs36 = require("fs");
8889
+ import_node_path32 = require("path");
8704
8890
  init_paths();
8705
8891
  }
8706
8892
  });
@@ -8753,6 +8939,7 @@ __export(index_exports, {
8753
8939
  CONTEXT_KEEP_RECENT_CHARS: () => CONTEXT_KEEP_RECENT_CHARS,
8754
8940
  CONTEXT_KEEP_RECENT_MESSAGES: () => CONTEXT_KEEP_RECENT_MESSAGES,
8755
8941
  CONTEXT_MIN_MESSAGES: () => CONTEXT_MIN_MESSAGES,
8942
+ CONVENTION_SETUP_RELPATHS: () => CONVENTION_SETUP_RELPATHS,
8756
8943
  COORDINATOR_TOOL_PLAYBOOK: () => COORDINATOR_TOOL_PLAYBOOK,
8757
8944
  FAMOUS_SOCCER_TEAMS: () => FAMOUS_SOCCER_TEAMS,
8758
8945
  GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
@@ -8914,6 +9101,7 @@ __export(index_exports, {
8914
9101
  extractiveSummary: () => extractiveSummary,
8915
9102
  fetchPrHead: () => fetchPrHead,
8916
9103
  finalizeParts: () => finalizeParts,
9104
+ findConventionSetup: () => findConventionSetup,
8917
9105
  findInvalidCacheControlTtlOrder: () => findInvalidCacheControlTtlOrder,
8918
9106
  findOrphanWorktrees: () => findOrphanWorktrees,
8919
9107
  findThreadByRef: () => findThreadByRef,
@@ -8985,6 +9173,7 @@ __export(index_exports, {
8985
9173
  hasBakedLinearOAuth: () => hasBakedLinearOAuth,
8986
9174
  hasBakedSlackOAuth: () => hasBakedSlackOAuth,
8987
9175
  hasConductorHook: () => hasConductorHook,
9176
+ hasConventionSetup: () => hasConventionSetup,
8988
9177
  hasCursorWorktreeSetup: () => hasCursorWorktreeSetup,
8989
9178
  hasRepoHook: () => hasRepoHook,
8990
9179
  hasWorkspaceHook: () => hasWorkspaceHook,
@@ -9160,10 +9349,12 @@ __export(index_exports, {
9160
9349
  run: () => run,
9161
9350
  runArchiveScript: () => runArchiveScript,
9162
9351
  runCloudConnect: () => runCloudConnect,
9352
+ runConventionSetup: () => runConventionSetup,
9163
9353
  runCursorWorktreeSetup: () => runCursorWorktreeSetup,
9164
9354
  runSetupScript: () => runSetupScript,
9165
9355
  runSlackListen: () => runSlackListen,
9166
9356
  runSlackRelayClient: () => runSlackRelayClient,
9357
+ runWorkspaceSetup: () => runWorkspaceSetup,
9167
9358
  sameWorktreePath: () => sameWorktreePath,
9168
9359
  sanitizeMcpServerName: () => sanitizeMcpServerName,
9169
9360
  saveAppSettings: () => saveAppSettings,
@@ -10009,8 +10200,8 @@ async function listIssues(repoPath) {
10009
10200
  init_agents();
10010
10201
 
10011
10202
  // src/agents/spawn.ts
10012
- var import_node_readline = require("readline");
10013
- var import_execa2 = require("execa");
10203
+ var import_node_readline2 = require("readline");
10204
+ var import_execa3 = require("execa");
10014
10205
  init_worktree();
10015
10206
  init_git_auth_mode();
10016
10207
  init_app_settings();
@@ -10286,7 +10477,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
10286
10477
  const detail = err instanceof Error ? err.message : String(err);
10287
10478
  console.warn(`[sideboard] git auth env failed (${thread.worktreePath}): ${detail}`);
10288
10479
  }
10289
- const child = (0, import_execa2.execa)(cmd.file, cmd.args, {
10480
+ const child = (0, import_execa3.execa)(cmd.file, cmd.args, {
10290
10481
  cwd: cmd.cwd,
10291
10482
  env,
10292
10483
  reject: false,
@@ -10306,7 +10497,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
10306
10497
  let usage = null;
10307
10498
  const consume = (stream, kind) => {
10308
10499
  if (!stream) return;
10309
- const rl = (0, import_node_readline.createInterface)({ input: stream, crlfDelay: Infinity });
10500
+ const rl = (0, import_node_readline2.createInterface)({ input: stream, crlfDelay: Infinity });
10310
10501
  rl.on("line", (line) => {
10311
10502
  if (kind === "stderr") {
10312
10503
  onEvent({ type: "stderr", data: line });
@@ -10373,11 +10564,11 @@ init_usage();
10373
10564
  init_claude_mcp();
10374
10565
 
10375
10566
  // src/agents/instructions.ts
10376
- var import_node_fs20 = require("fs");
10377
- var import_node_path17 = require("path");
10567
+ var import_node_fs22 = require("fs");
10568
+ var import_node_path19 = require("path");
10378
10569
  init_git_auth_mode();
10379
10570
  init_worktree_labels();
10380
- function normPath2(p) {
10571
+ function normPath3(p) {
10381
10572
  return p.replace(/\/+$/, "");
10382
10573
  }
10383
10574
  function formatRenameBranchDirective(thread, opts) {
@@ -10398,8 +10589,8 @@ function formatRenameBranchDirective(thread, opts) {
10398
10589
  return lines.join("\n");
10399
10590
  }
10400
10591
  function formatWorktreeDirective(thread, opts) {
10401
- const worktree = normPath2(thread.worktreePath);
10402
- const repo = normPath2(thread.repoPath);
10592
+ const worktree = normPath3(thread.worktreePath);
10593
+ const repo = normPath3(thread.repoPath);
10403
10594
  const dir = worktreeNameFromPath(thread.worktreePath);
10404
10595
  const lines = [
10405
10596
  "Sideboard workspace (mandatory):",
@@ -10544,11 +10735,11 @@ function loadAgentInstructions(worktreePath, agent) {
10544
10735
  const out = [];
10545
10736
  for (const rel of candidates) {
10546
10737
  if (seenPaths.has(rel)) continue;
10547
- const abs = (0, import_node_path17.join)(worktreePath, rel);
10548
- if (!(0, import_node_fs20.existsSync)(abs)) continue;
10738
+ const abs = (0, import_node_path19.join)(worktreePath, rel);
10739
+ if (!(0, import_node_fs22.existsSync)(abs)) continue;
10549
10740
  try {
10550
- if (!(0, import_node_fs20.statSync)(abs).isFile()) continue;
10551
- let content = (0, import_node_fs20.readFileSync)(abs, "utf8");
10741
+ if (!(0, import_node_fs22.statSync)(abs).isFile()) continue;
10742
+ let content = (0, import_node_fs22.readFileSync)(abs, "utf8");
10552
10743
  if (!content.trim()) continue;
10553
10744
  if (content.length > MAX_CHARS_PER_FILE) {
10554
10745
  content = `${content.slice(0, MAX_CHARS_PER_FILE)}
@@ -10630,13 +10821,15 @@ async function requireAgent(agent, opts) {
10630
10821
  init_settings();
10631
10822
 
10632
10823
  // src/hook/conductor.ts
10633
- var import_node_fs21 = require("fs");
10824
+ var import_node_fs23 = require("fs");
10634
10825
  var import_node_net = require("net");
10635
- var import_node_path18 = require("path");
10636
- var import_execa3 = require("execa");
10637
- var import_node_readline2 = require("readline");
10826
+ var import_node_path20 = require("path");
10827
+ var import_execa4 = require("execa");
10828
+ var import_node_readline3 = require("readline");
10638
10829
  init_settings();
10639
10830
  init_nested_electron_env();
10831
+ init_convention_setup();
10832
+ init_cursor_worktrees();
10640
10833
  init_git_auth_mode();
10641
10834
  init_nested_electron_env();
10642
10835
  var PORT_RANGE_SIZE = 10;
@@ -10645,9 +10838,9 @@ function matchSimpleGlob(pattern, name) {
10645
10838
  return new RegExp(`^${escaped}$`).test(name);
10646
10839
  }
10647
10840
  function readWorktreeInclude(repoPath) {
10648
- const path2 = (0, import_node_path18.join)(repoPath, ".worktreeinclude");
10649
- if (!(0, import_node_fs21.existsSync)(path2)) return [];
10650
- return (0, import_node_fs21.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
10841
+ const path2 = (0, import_node_path20.join)(repoPath, ".worktreeinclude");
10842
+ if (!(0, import_node_fs23.existsSync)(path2)) return [];
10843
+ return (0, import_node_fs23.readFileSync)(path2, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
10651
10844
  }
10652
10845
  function resolveFilesToCopy(repoPath) {
10653
10846
  const fromInclude = readWorktreeInclude(repoPath);
@@ -10657,10 +10850,10 @@ function resolveFilesToCopy(repoPath) {
10657
10850
  if (settings?.fileIncludeGlobs?.length) {
10658
10851
  const matched = [];
10659
10852
  try {
10660
- for (const entry of (0, import_node_fs21.readdirSync)(repoPath, { withFileTypes: true })) {
10853
+ for (const entry of (0, import_node_fs23.readdirSync)(repoPath, { withFileTypes: true })) {
10661
10854
  if (!entry.isFile()) continue;
10662
10855
  for (const glob of settings.fileIncludeGlobs) {
10663
- if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path18.basename)(glob), entry.name)) {
10856
+ if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path20.basename)(glob), entry.name)) {
10664
10857
  matched.push(entry.name);
10665
10858
  break;
10666
10859
  }
@@ -10672,7 +10865,7 @@ function resolveFilesToCopy(repoPath) {
10672
10865
  }
10673
10866
  const defaults = [];
10674
10867
  try {
10675
- for (const entry of (0, import_node_fs21.readdirSync)(repoPath, { withFileTypes: true })) {
10868
+ for (const entry of (0, import_node_fs23.readdirSync)(repoPath, { withFileTypes: true })) {
10676
10869
  if (entry.isFile() && entry.name.startsWith(".env")) {
10677
10870
  defaults.push(entry.name);
10678
10871
  }
@@ -10686,11 +10879,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
10686
10879
  const patterns = resolveFilesToCopy(repoPath);
10687
10880
  const copied = [];
10688
10881
  for (const rel of patterns) {
10689
- const src = (0, import_node_path18.join)(repoPath, rel);
10690
- if (!(0, import_node_fs21.existsSync)(src)) continue;
10691
- const dest = (0, import_node_path18.join)(worktreePath, rel);
10692
- (0, import_node_fs21.mkdirSync)((0, import_node_path18.dirname)(dest), { recursive: true });
10693
- (0, import_node_fs21.copyFileSync)(src, dest);
10882
+ const src = (0, import_node_path20.join)(repoPath, rel);
10883
+ if (!(0, import_node_fs23.existsSync)(src)) continue;
10884
+ const dest = (0, import_node_path20.join)(worktreePath, rel);
10885
+ (0, import_node_fs23.mkdirSync)((0, import_node_path20.dirname)(dest), { recursive: true });
10886
+ (0, import_node_fs23.copyFileSync)(src, dest);
10694
10887
  copied.push(rel);
10695
10888
  }
10696
10889
  return copied;
@@ -10700,7 +10893,7 @@ async function captureLoginEnv() {
10700
10893
  if (cachedLoginEnv) return { ...cachedLoginEnv };
10701
10894
  const shell = process.env.SHELL?.trim() || (process.platform === "darwin" ? "/bin/zsh" : "/bin/bash");
10702
10895
  try {
10703
- const result = await (0, import_execa3.execa)(shell, ["-l", "-c", "env -0"], {
10896
+ const result = await (0, import_execa4.execa)(shell, ["-l", "-c", "env -0"], {
10704
10897
  reject: false,
10705
10898
  timeout: 5e3
10706
10899
  });
@@ -10726,7 +10919,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
10726
10919
  const env = stripNestedElectronEnv({
10727
10920
  ...baseEnv ?? process.env
10728
10921
  });
10729
- const name = opts.workspaceName ?? (0, import_node_path18.basename)(opts.worktreePath);
10922
+ const name = opts.workspaceName ?? (0, import_node_path20.basename)(opts.worktreePath);
10730
10923
  const ports = opts.ports ?? [];
10731
10924
  const primary = ports[0];
10732
10925
  env.SIDEBOARD_WORKSPACE_NAME = name;
@@ -10753,7 +10946,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
10753
10946
  }
10754
10947
  function pipeLines(stream, onLine) {
10755
10948
  if (!stream || !onLine) return;
10756
- const rl = (0, import_node_readline2.createInterface)({ input: stream });
10949
+ const rl = (0, import_node_readline3.createInterface)({ input: stream });
10757
10950
  rl.on("line", onLine);
10758
10951
  }
10759
10952
  function killScriptTree(child, ports = []) {
@@ -10761,7 +10954,7 @@ function killScriptTree(child, ports = []) {
10761
10954
  if (pid) {
10762
10955
  try {
10763
10956
  if (process.platform === "win32") {
10764
- void (0, import_execa3.execa)("taskkill", ["/pid", String(pid), "/T", "/F"], { reject: false });
10957
+ void (0, import_execa4.execa)("taskkill", ["/pid", String(pid), "/T", "/F"], { reject: false });
10765
10958
  } else {
10766
10959
  process.kill(-pid, "SIGTERM");
10767
10960
  setTimeout(() => {
@@ -10781,7 +10974,7 @@ function killScriptTree(child, ports = []) {
10781
10974
  for (const port of ports) {
10782
10975
  if (!Number.isFinite(port) || port <= 0) continue;
10783
10976
  if (process.platform === "win32") {
10784
- void (0, import_execa3.execa)(
10977
+ void (0, import_execa4.execa)(
10785
10978
  "powershell",
10786
10979
  [
10787
10980
  "-NoProfile",
@@ -10791,7 +10984,7 @@ function killScriptTree(child, ports = []) {
10791
10984
  { reject: false }
10792
10985
  );
10793
10986
  } else {
10794
- void (0, import_execa3.execa)(
10987
+ void (0, import_execa4.execa)(
10795
10988
  "zsh",
10796
10989
  ["-lc", `pids=$(lsof -tiTCP:${port} -sTCP:LISTEN 2>/dev/null); [ -n "$pids" ] && kill -TERM $pids 2>/dev/null; true`],
10797
10990
  { reject: false }
@@ -10816,7 +11009,7 @@ async function spawnWorkspaceScript(command, opts) {
10816
11009
  } catch {
10817
11010
  }
10818
11011
  const shell = process.platform === "darwin" ? "zsh" : "bash";
10819
- const child = (0, import_execa3.execa)(shell, ["-lc", command], {
11012
+ const child = (0, import_execa4.execa)(shell, ["-lc", command], {
10820
11013
  cwd: opts.worktreePath,
10821
11014
  reject: false,
10822
11015
  env,
@@ -10834,6 +11027,14 @@ async function spawnWorkspaceScript(command, opts) {
10834
11027
  child
10835
11028
  };
10836
11029
  }
11030
+ async function attachAbort(handle, signal) {
11031
+ if (signal) {
11032
+ const onAbort = () => handle.kill();
11033
+ if (signal.aborted) onAbort();
11034
+ else signal.addEventListener("abort", onAbort, { once: true });
11035
+ }
11036
+ return handle.done;
11037
+ }
10837
11038
  async function runSetupScript(repoPath, worktreePath, onLine, opts) {
10838
11039
  const settings = loadWorkspaceSettings(worktreePath, repoPath);
10839
11040
  if (!settings?.setup) return { ran: false, exitCode: null, source: null };
@@ -10843,12 +11044,7 @@ async function runSetupScript(repoPath, worktreePath, onLine, opts) {
10843
11044
  defaultBranch: opts?.defaultBranch,
10844
11045
  onLine
10845
11046
  });
10846
- if (opts?.signal) {
10847
- const onAbort = () => handle.kill();
10848
- if (opts.signal.aborted) onAbort();
10849
- else opts.signal.addEventListener("abort", onAbort, { once: true });
10850
- }
10851
- const exitCode = await handle.done;
11047
+ const exitCode = await attachAbort(handle, opts?.signal);
10852
11048
  return {
10853
11049
  ran: true,
10854
11050
  exitCode,
@@ -10856,6 +11052,34 @@ async function runSetupScript(repoPath, worktreePath, onLine, opts) {
10856
11052
  kill: handle.kill
10857
11053
  };
10858
11054
  }
11055
+ async function runConventionSetup(repoPath, worktreePath, onLine, opts) {
11056
+ const found = findConventionSetup(worktreePath, repoPath);
11057
+ if (!found) return { ran: false, exitCode: null, source: null };
11058
+ onLine?.(`[setup] ${found.source}`);
11059
+ const handle = await spawnWorkspaceScript(found.command, {
11060
+ worktreePath,
11061
+ repoPath,
11062
+ defaultBranch: opts?.defaultBranch,
11063
+ onLine
11064
+ });
11065
+ const exitCode = await attachAbort(handle, opts?.signal);
11066
+ return {
11067
+ ran: true,
11068
+ exitCode,
11069
+ source: found.source,
11070
+ kill: handle.kill
11071
+ };
11072
+ }
11073
+ async function runWorkspaceSetup(repoPath, worktreePath, onLine, opts) {
11074
+ let setup = await runSetupScript(repoPath, worktreePath, onLine, opts);
11075
+ if (!setup.ran) {
11076
+ setup = await runCursorWorktreeSetup(repoPath, worktreePath, onLine);
11077
+ }
11078
+ if (!setup.ran) {
11079
+ setup = await runConventionSetup(repoPath, worktreePath, onLine, opts);
11080
+ }
11081
+ return setup;
11082
+ }
10859
11083
  async function runArchiveScript(repoPath, worktreePath, onLine) {
10860
11084
  const settings = loadWorkspaceSettings(worktreePath, repoPath);
10861
11085
  if (!settings?.archive) return { ran: false, exitCode: null };
@@ -10948,86 +11172,17 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
10948
11172
  };
10949
11173
  }
10950
11174
 
10951
- // src/hook/cursor-worktrees.ts
10952
- var import_node_fs22 = require("fs");
10953
- var import_node_path19 = require("path");
10954
- var import_execa4 = require("execa");
10955
- var import_node_readline3 = require("readline");
10956
- function loadCursorWorktreesJson(rootPath) {
10957
- const path2 = (0, import_node_path19.join)(rootPath, ".cursor", "worktrees.json");
10958
- if (!(0, import_node_fs22.existsSync)(path2)) return null;
10959
- try {
10960
- return JSON.parse((0, import_node_fs22.readFileSync)(path2, "utf8"));
10961
- } catch {
10962
- return null;
10963
- }
10964
- }
10965
- function resolveSetupSpec(config) {
10966
- if (process.platform === "win32") {
10967
- return config["setup-worktree-windows"] ?? config["setup-worktree"] ?? null;
10968
- }
10969
- return config["setup-worktree-unix"] ?? config["setup-worktree"] ?? null;
10970
- }
10971
- async function runCursorWorktreeSetup(repoPath, worktreePath, onLine) {
10972
- const fromWorktree = loadCursorWorktreesJson(worktreePath);
10973
- const fromRepo = worktreePath !== repoPath ? loadCursorWorktreesJson(repoPath) : null;
10974
- const config = fromWorktree ?? fromRepo;
10975
- if (!config) return { ran: false, exitCode: null, source: null };
10976
- const spec = resolveSetupSpec(config);
10977
- if (!spec) return { ran: false, exitCode: null, source: null };
10978
- const sourceLabel = fromWorktree ? ".cursor/worktrees.json (worktree)" : ".cursor/worktrees.json (main repo)";
10979
- const env = {
10980
- ...process.env,
10981
- ROOT_WORKTREE_PATH: repoPath
10982
- };
10983
- if (process.platform === "win32") {
10984
- env.ROOT_WORKTREE_PATH = repoPath;
10985
- }
10986
- const commands = Array.isArray(spec) ? spec : [spec.endsWith(".sh") || spec.endsWith(".ps1") ? (0, import_node_path19.join)(
10987
- fromWorktree ? worktreePath : repoPath,
10988
- ".cursor",
10989
- spec
10990
- ) : spec];
10991
- let lastExit = 0;
10992
- for (const command of commands) {
10993
- const isScriptPath = typeof spec === "string" && (spec.endsWith(".sh") || spec.endsWith(".ps1"));
10994
- const shell = process.platform === "win32" ? "powershell" : "bash";
10995
- const args = process.platform === "win32" ? isScriptPath ? ["-File", command] : ["-Command", command] : isScriptPath ? [command] : ["-lc", command];
10996
- onLine?.(`[cursor setup] ${command}`);
10997
- const child = (0, import_execa4.execa)(shell, args, {
10998
- cwd: worktreePath,
10999
- reject: false,
11000
- env
11001
- });
11002
- if (child.stdout && onLine) {
11003
- const rl = (0, import_node_readline3.createInterface)({ input: child.stdout });
11004
- rl.on("line", onLine);
11005
- }
11006
- if (child.stderr && onLine) {
11007
- const rl = (0, import_node_readline3.createInterface)({ input: child.stderr });
11008
- rl.on("line", onLine);
11009
- }
11010
- const result = await child;
11011
- lastExit = result.exitCode ?? null;
11012
- if (lastExit !== 0 && lastExit !== null) break;
11013
- }
11014
- return { ran: true, exitCode: lastExit, source: sourceLabel };
11015
- }
11016
- function hasCursorWorktreeSetup(worktreePath, repoPath) {
11017
- if (loadCursorWorktreesJson(worktreePath)) return true;
11018
- if (repoPath && repoPath !== worktreePath && loadCursorWorktreesJson(repoPath)) {
11019
- return true;
11020
- }
11021
- return false;
11022
- }
11175
+ // src/index.ts
11176
+ init_convention_setup();
11177
+ init_cursor_worktrees();
11023
11178
 
11024
11179
  // src/diff/diff.ts
11025
- var import_node_fs23 = require("fs");
11026
- var import_node_path20 = require("path");
11180
+ var import_node_fs24 = require("fs");
11181
+ var import_node_path21 = require("path");
11027
11182
  init_run();
11028
11183
  init_worktree();
11029
11184
  async function inspectGitWorktree(worktreePath) {
11030
- if (!worktreePath || !(0, import_node_fs23.existsSync)(worktreePath)) return "missing_worktree";
11185
+ if (!worktreePath || !(0, import_node_fs24.existsSync)(worktreePath)) return "missing_worktree";
11031
11186
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
11032
11187
  reject: false
11033
11188
  });
@@ -11035,7 +11190,7 @@ async function inspectGitWorktree(worktreePath) {
11035
11190
  return "ok";
11036
11191
  }
11037
11192
  async function initializeGitRepository(worktreePath) {
11038
- if (!worktreePath || !(0, import_node_fs23.existsSync)(worktreePath)) {
11193
+ if (!worktreePath || !(0, import_node_fs24.existsSync)(worktreePath)) {
11039
11194
  throw new Error("Worktree not found");
11040
11195
  }
11041
11196
  const status = await inspectGitWorktree(worktreePath);
@@ -11170,11 +11325,11 @@ new file mode 100644
11170
11325
  };
11171
11326
  }
11172
11327
  async function untrackedPatch(worktreePath, path2, maxHunk) {
11173
- const abs = (0, import_node_path20.join)(worktreePath, path2);
11328
+ const abs = (0, import_node_path21.join)(worktreePath, path2);
11174
11329
  try {
11175
- const st = (0, import_node_fs23.statSync)(abs);
11330
+ const st = (0, import_node_fs24.statSync)(abs);
11176
11331
  if (st.isFile() && st.size > maxHunk) {
11177
- const buf = (0, import_node_fs23.readFileSync)(abs).subarray(0, maxHunk);
11332
+ const buf = (0, import_node_fs24.readFileSync)(abs).subarray(0, maxHunk);
11178
11333
  return syntheticAddPatch(path2, buf.toString("utf8"), maxHunk);
11179
11334
  }
11180
11335
  } catch {
@@ -11675,8 +11830,8 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
11675
11830
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
11676
11831
  assertSafeRelativePath(relativePath);
11677
11832
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
11678
- const abs = (0, import_node_path20.join)(worktreePath, relativePath);
11679
- const st = (0, import_node_fs23.statSync)(abs);
11833
+ const abs = (0, import_node_path21.join)(worktreePath, relativePath);
11834
+ const st = (0, import_node_fs24.statSync)(abs);
11680
11835
  if (!st.isFile()) {
11681
11836
  throw new Error(`Not a file: ${relativePath}`);
11682
11837
  }
@@ -11685,7 +11840,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
11685
11840
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
11686
11841
  );
11687
11842
  }
11688
- const buf = (0, import_node_fs23.readFileSync)(abs);
11843
+ const buf = (0, import_node_fs24.readFileSync)(abs);
11689
11844
  return {
11690
11845
  path: relativePath,
11691
11846
  contentBase64: buf.toString("base64"),
@@ -11695,12 +11850,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
11695
11850
  function readWorktreeFile(worktreePath, relativePath, opts) {
11696
11851
  assertSafeRelativePath(relativePath);
11697
11852
  const maxBytes = opts?.maxBytes ?? 2e5;
11698
- const abs = (0, import_node_path20.join)(worktreePath, relativePath);
11699
- const st = (0, import_node_fs23.statSync)(abs);
11853
+ const abs = (0, import_node_path21.join)(worktreePath, relativePath);
11854
+ const st = (0, import_node_fs24.statSync)(abs);
11700
11855
  if (!st.isFile()) {
11701
11856
  throw new Error(`Not a file: ${relativePath}`);
11702
11857
  }
11703
- const buf = (0, import_node_fs23.readFileSync)(abs);
11858
+ const buf = (0, import_node_fs24.readFileSync)(abs);
11704
11859
  if (isImageRelativePath(relativePath)) {
11705
11860
  const maxImageBytes = Math.max(maxBytes, 15e6);
11706
11861
  const truncated2 = buf.length > maxImageBytes;
@@ -11743,9 +11898,9 @@ function assertSafeRelativePath(relativePath) {
11743
11898
  }
11744
11899
  function writeWorktreeFile(worktreePath, relativePath, content) {
11745
11900
  assertSafeRelativePath(relativePath);
11746
- const abs = (0, import_node_path20.join)(worktreePath, relativePath);
11747
- (0, import_node_fs23.mkdirSync)((0, import_node_path20.dirname)(abs), { recursive: true });
11748
- (0, import_node_fs23.writeFileSync)(abs, content, "utf8");
11901
+ const abs = (0, import_node_path21.join)(worktreePath, relativePath);
11902
+ (0, import_node_fs24.mkdirSync)((0, import_node_path21.dirname)(abs), { recursive: true });
11903
+ (0, import_node_fs24.writeFileSync)(abs, content, "utf8");
11749
11904
  return { path: relativePath };
11750
11905
  }
11751
11906
  async function getDiffSummary(worktreePath, repoPath, opts) {
@@ -11764,9 +11919,9 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
11764
11919
  }
11765
11920
 
11766
11921
  // src/skills/discover.ts
11767
- var import_node_fs24 = require("fs");
11922
+ var import_node_fs25 = require("fs");
11768
11923
  var import_node_os8 = require("os");
11769
- var import_node_path21 = require("path");
11924
+ var import_node_path22 = require("path");
11770
11925
  function toCommand(name) {
11771
11926
  return name.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
11772
11927
  }
@@ -11798,7 +11953,7 @@ function parseFrontmatter(content) {
11798
11953
  }
11799
11954
  function readSkill(skillMd, source) {
11800
11955
  try {
11801
- const content = (0, import_node_fs24.readFileSync)(skillMd, "utf8");
11956
+ const content = (0, import_node_fs25.readFileSync)(skillMd, "utf8");
11802
11957
  const { name: fmName, description } = parseFrontmatter(content);
11803
11958
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
11804
11959
  const name = fmName || dirName;
@@ -11817,19 +11972,19 @@ function readSkill(skillMd, source) {
11817
11972
  }
11818
11973
  }
11819
11974
  function scanSkillsDir(dir, source, out) {
11820
- if (!(0, import_node_fs24.existsSync)(dir)) return;
11975
+ if (!(0, import_node_fs25.existsSync)(dir)) return;
11821
11976
  let entries;
11822
11977
  try {
11823
- entries = (0, import_node_fs24.readdirSync)(dir);
11978
+ entries = (0, import_node_fs25.readdirSync)(dir);
11824
11979
  } catch {
11825
11980
  return;
11826
11981
  }
11827
11982
  for (const entry of entries) {
11828
11983
  if (entry.startsWith(".")) continue;
11829
- const skillMd = (0, import_node_path21.join)(dir, entry, "SKILL.md");
11830
- if (!(0, import_node_fs24.existsSync)(skillMd)) continue;
11984
+ const skillMd = (0, import_node_path22.join)(dir, entry, "SKILL.md");
11985
+ if (!(0, import_node_fs25.existsSync)(skillMd)) continue;
11831
11986
  try {
11832
- if (!(0, import_node_fs24.statSync)(skillMd).isFile()) continue;
11987
+ if (!(0, import_node_fs25.statSync)(skillMd).isFile()) continue;
11833
11988
  } catch {
11834
11989
  continue;
11835
11990
  }
@@ -11838,24 +11993,24 @@ function scanSkillsDir(dir, source, out) {
11838
11993
  }
11839
11994
  }
11840
11995
  function scanClaudePluginSkills(pluginsRoot, out) {
11841
- if (!(0, import_node_fs24.existsSync)(pluginsRoot)) return;
11996
+ if (!(0, import_node_fs25.existsSync)(pluginsRoot)) return;
11842
11997
  const walk = (dir, depth, lookingForSkillsDir) => {
11843
11998
  if (depth > 7) return;
11844
11999
  let entries;
11845
12000
  try {
11846
- entries = (0, import_node_fs24.readdirSync)(dir);
12001
+ entries = (0, import_node_fs25.readdirSync)(dir);
11847
12002
  } catch {
11848
12003
  return;
11849
12004
  }
11850
12005
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
11851
- const skill = readSkill((0, import_node_path21.join)(dir, "SKILL.md"), "cli");
12006
+ const skill = readSkill((0, import_node_path22.join)(dir, "SKILL.md"), "cli");
11852
12007
  if (skill) out.push(skill);
11853
12008
  }
11854
12009
  for (const entry of entries) {
11855
12010
  if (entry === "node_modules" || entry === ".git") continue;
11856
- const full = (0, import_node_path21.join)(dir, entry);
12011
+ const full = (0, import_node_path22.join)(dir, entry);
11857
12012
  try {
11858
- if (!(0, import_node_fs24.statSync)(full).isDirectory()) continue;
12013
+ if (!(0, import_node_fs25.statSync)(full).isDirectory()) continue;
11859
12014
  } catch {
11860
12015
  continue;
11861
12016
  }
@@ -11873,17 +12028,17 @@ function discoverSkills(worktreePath) {
11873
12028
  const home = (0, import_node_os8.homedir)();
11874
12029
  const collected = [];
11875
12030
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
11876
- scanSkillsDir((0, import_node_path21.join)(worktreePath, rel), "workspace", collected);
12031
+ scanSkillsDir((0, import_node_path22.join)(worktreePath, rel), "workspace", collected);
11877
12032
  }
11878
12033
  for (const abs of [
11879
- (0, import_node_path21.join)(home, ".claude/skills"),
11880
- (0, import_node_path21.join)(home, ".cursor/skills"),
11881
- (0, import_node_path21.join)(home, ".sideboard/skills"),
11882
- (0, import_node_path21.join)(home, ".brightsy/skills")
12034
+ (0, import_node_path22.join)(home, ".claude/skills"),
12035
+ (0, import_node_path22.join)(home, ".cursor/skills"),
12036
+ (0, import_node_path22.join)(home, ".sideboard/skills"),
12037
+ (0, import_node_path22.join)(home, ".brightsy/skills")
11883
12038
  ]) {
11884
12039
  scanSkillsDir(abs, "user", collected);
11885
12040
  }
11886
- scanClaudePluginSkills((0, import_node_path21.join)(home, ".claude/plugins"), collected);
12041
+ scanClaudePluginSkills((0, import_node_path22.join)(home, ".claude/plugins"), collected);
11887
12042
  const rank = { workspace: 0, user: 1, cli: 2 };
11888
12043
  const byCommand = /* @__PURE__ */ new Map();
11889
12044
  for (const skill of collected) {
@@ -11895,7 +12050,7 @@ function discoverSkills(worktreePath) {
11895
12050
  return [...byCommand.values()].sort((a, b) => a.command.localeCompare(b.command));
11896
12051
  }
11897
12052
  function readSkillBody(skillPath, maxChars = 12e3) {
11898
- const raw = (0, import_node_fs24.readFileSync)(skillPath, "utf8");
12053
+ const raw = (0, import_node_fs25.readFileSync)(skillPath, "utf8");
11899
12054
  if (raw.startsWith("---")) {
11900
12055
  const end = raw.indexOf("\n---", 3);
11901
12056
  if (end >= 0) {
@@ -12036,8 +12191,8 @@ function buildDiffCommentAttachment(input) {
12036
12191
  }
12037
12192
 
12038
12193
  // src/composer/stage-files.ts
12039
- var import_node_fs25 = require("fs");
12040
- var import_node_path22 = require("path");
12194
+ var import_node_fs26 = require("fs");
12195
+ var import_node_path23 = require("path");
12041
12196
  var import_node_crypto5 = require("crypto");
12042
12197
  init_workspace_scratch();
12043
12198
  var IMAGE_EXTENSIONS2 = /* @__PURE__ */ new Set([
@@ -12063,7 +12218,7 @@ var IMAGE_MIME_BY_EXT = {
12063
12218
  var MAX_INLINE_BYTES = 4e5;
12064
12219
  var MAX_PREVIEW_BYTES = 5e6;
12065
12220
  function fileExtension(filePath) {
12066
- const base = (0, import_node_path22.basename)(filePath).toLowerCase();
12221
+ const base = (0, import_node_path23.basename)(filePath).toLowerCase();
12067
12222
  return base.includes(".") ? base.split(".").pop() || "" : "";
12068
12223
  }
12069
12224
  function isImageFilePath(filePath) {
@@ -12073,22 +12228,22 @@ function imageMimeType(filePath) {
12073
12228
  return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
12074
12229
  }
12075
12230
  function ensureAttachmentsDir(worktreePath) {
12076
- const dir = (0, import_node_path22.join)(worktreePath, ATTACHMENTS_DIR);
12077
- (0, import_node_fs25.mkdirSync)(dir, { recursive: true });
12078
- const gi = (0, import_node_path22.join)(dir, ".gitignore");
12079
- if (!(0, import_node_fs25.existsSync)(gi)) {
12080
- (0, import_node_fs25.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
12231
+ const dir = (0, import_node_path23.join)(worktreePath, ATTACHMENTS_DIR);
12232
+ (0, import_node_fs26.mkdirSync)(dir, { recursive: true });
12233
+ const gi = (0, import_node_path23.join)(dir, ".gitignore");
12234
+ if (!(0, import_node_fs26.existsSync)(gi)) {
12235
+ (0, import_node_fs26.writeFileSync)(gi, attachmentsGitignoreBody(), "utf8");
12081
12236
  }
12082
12237
  return dir;
12083
12238
  }
12084
12239
  function uniqueAttachmentName(dir, originalName) {
12085
12240
  const safe = originalName.replace(/[/\\]/g, "_") || "file";
12086
- if (!(0, import_node_fs25.existsSync)((0, import_node_path22.join)(dir, safe))) return safe;
12087
- const ext = (0, import_node_path22.extname)(safe);
12241
+ if (!(0, import_node_fs26.existsSync)((0, import_node_path23.join)(dir, safe))) return safe;
12242
+ const ext = (0, import_node_path23.extname)(safe);
12088
12243
  const stem = ext ? safe.slice(0, -ext.length) : safe;
12089
12244
  for (let i = 1; i < 1e4; i++) {
12090
12245
  const candidate = `${stem}-${i}${ext}`;
12091
- if (!(0, import_node_fs25.existsSync)((0, import_node_path22.join)(dir, candidate))) return candidate;
12246
+ if (!(0, import_node_fs26.existsSync)((0, import_node_path23.join)(dir, candidate))) return candidate;
12092
12247
  }
12093
12248
  return `${stem}-${(0, import_node_crypto5.randomUUID)()}${ext}`;
12094
12249
  }
@@ -12140,9 +12295,9 @@ function attachmentFromBuffer(name, buf, opts) {
12140
12295
  };
12141
12296
  }
12142
12297
  function attachmentFromAbsolutePath(absolutePath) {
12143
- const name = (0, import_node_path22.basename)(absolutePath);
12298
+ const name = (0, import_node_path23.basename)(absolutePath);
12144
12299
  try {
12145
- const st = (0, import_node_fs25.statSync)(absolutePath);
12300
+ const st = (0, import_node_fs26.statSync)(absolutePath);
12146
12301
  if (!st.isFile()) {
12147
12302
  return {
12148
12303
  id: (0, import_node_crypto5.randomUUID)(),
@@ -12151,7 +12306,7 @@ function attachmentFromAbsolutePath(absolutePath) {
12151
12306
  content: `(not a file: ${absolutePath})`
12152
12307
  };
12153
12308
  }
12154
- const buf = (0, import_node_fs25.readFileSync)(absolutePath);
12309
+ const buf = (0, import_node_fs26.readFileSync)(absolutePath);
12155
12310
  return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
12156
12311
  } catch (err) {
12157
12312
  return {
@@ -12167,15 +12322,15 @@ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
12167
12322
  const dir = ensureAttachmentsDir(worktreePath);
12168
12323
  const out = [];
12169
12324
  for (const abs of absolutePaths) {
12170
- const originalName = (0, import_node_path22.basename)(abs);
12325
+ const originalName = (0, import_node_path23.basename)(abs);
12171
12326
  try {
12172
- const st = (0, import_node_fs25.statSync)(abs);
12327
+ const st = (0, import_node_fs26.statSync)(abs);
12173
12328
  if (!st.isFile()) continue;
12174
12329
  const name = uniqueAttachmentName(dir, originalName);
12175
- const destAbs = (0, import_node_path22.join)(dir, name);
12176
- (0, import_node_fs25.copyFileSync)(abs, destAbs);
12330
+ const destAbs = (0, import_node_path23.join)(dir, name);
12331
+ (0, import_node_fs26.copyFileSync)(abs, destAbs);
12177
12332
  const rel = `${ATTACHMENTS_DIR}/${name}`;
12178
- const buf = (0, import_node_fs25.readFileSync)(destAbs);
12333
+ const buf = (0, import_node_fs26.readFileSync)(destAbs);
12179
12334
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
12180
12335
  } catch (err) {
12181
12336
  out.push({
@@ -12197,8 +12352,8 @@ function stageBuffersAsAttachments(worktreePath, buffers) {
12197
12352
  try {
12198
12353
  const buf = Buffer.from(item.dataBase64, "base64");
12199
12354
  const name = uniqueAttachmentName(dir, originalName);
12200
- const destAbs = (0, import_node_path22.join)(dir, name);
12201
- (0, import_node_fs25.writeFileSync)(destAbs, buf);
12355
+ const destAbs = (0, import_node_path23.join)(dir, name);
12356
+ (0, import_node_fs26.writeFileSync)(destAbs, buf);
12202
12357
  const rel = `${ATTACHMENTS_DIR}/${name}`;
12203
12358
  out.push(attachmentFromBuffer(name, buf, { path: rel }));
12204
12359
  } catch (err) {
@@ -12234,18 +12389,18 @@ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
12234
12389
  if (!rel || rel.includes("..") || rel.startsWith("/")) {
12235
12390
  out.push({
12236
12391
  id: (0, import_node_crypto5.randomUUID)(),
12237
- name: (0, import_node_path22.basename)(rel) || "file",
12392
+ name: (0, import_node_path23.basename)(rel) || "file",
12238
12393
  kind: "file",
12239
12394
  content: `(invalid path: ${rel})`
12240
12395
  });
12241
12396
  continue;
12242
12397
  }
12243
- const name = (0, import_node_path22.basename)(rel);
12398
+ const name = (0, import_node_path23.basename)(rel);
12244
12399
  try {
12245
- const abs = (0, import_node_path22.join)(worktreePath, rel);
12246
- const st = (0, import_node_fs25.statSync)(abs);
12400
+ const abs = (0, import_node_path23.join)(worktreePath, rel);
12401
+ const st = (0, import_node_fs26.statSync)(abs);
12247
12402
  if (!st.isFile()) continue;
12248
- const buf = (0, import_node_fs25.readFileSync)(abs);
12403
+ const buf = (0, import_node_fs26.readFileSync)(abs);
12249
12404
  out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
12250
12405
  } catch (err) {
12251
12406
  out.push({
@@ -12733,7 +12888,7 @@ async function confirmLand(thread, opts) {
12733
12888
  }
12734
12889
 
12735
12890
  // src/threads/create.ts
12736
- var import_node_fs26 = require("fs");
12891
+ var import_node_fs27 = require("fs");
12737
12892
  init_worktree();
12738
12893
  init_app_settings();
12739
12894
  init_thread_store();
@@ -12747,7 +12902,7 @@ async function createThread(input, _onSetupLine) {
12747
12902
  });
12748
12903
  await requireAgent(resolved.agent);
12749
12904
  const repoPath = await resolveRepoRoot(input.repoPath);
12750
- if (!(0, import_node_fs26.existsSync)(repoPath)) {
12905
+ if (!(0, import_node_fs27.existsSync)(repoPath)) {
12751
12906
  throw new Error(`Repo not found: ${repoPath}`);
12752
12907
  }
12753
12908
  let sourceRef = input.sourceRef;
@@ -12974,7 +13129,7 @@ async function forkThreadWorktree(input, onSetupLine) {
12974
13129
  }
12975
13130
 
12976
13131
  // src/threads/stack-layers.ts
12977
- var import_node_fs27 = require("fs");
13132
+ var import_node_fs28 = require("fs");
12978
13133
  init_run();
12979
13134
  init_stack();
12980
13135
  init_worktree();
@@ -13042,7 +13197,7 @@ async function openStackLayer(input, _onSetupLine) {
13042
13197
  let createdWorktree = false;
13043
13198
  const trees = await listWorktrees(repoPath);
13044
13199
  const checkedOut = trees.find((w) => w.branch === branchName);
13045
- if (checkedOut?.path && (0, import_node_fs27.existsSync)(checkedOut.path)) {
13200
+ if (checkedOut?.path && (0, import_node_fs28.existsSync)(checkedOut.path)) {
13046
13201
  if (input.reuseExistingWorktree !== false) {
13047
13202
  worktreePath = checkedOut.path;
13048
13203
  } else {
@@ -13184,7 +13339,7 @@ async function initStackFromThread(input, onSetupLine) {
13184
13339
  async function createPrStack(input, onSetupLine) {
13185
13340
  await requireAgent(input.agent);
13186
13341
  const repoPath = await resolveRepoRoot(input.repoPath);
13187
- if (!(0, import_node_fs27.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
13342
+ if (!(0, import_node_fs28.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
13188
13343
  if (!input.branches.length) throw new Error("At least one branch name required");
13189
13344
  const status = await detectGhStack(repoPath);
13190
13345
  if (!status.available) throw new Error(status.reason);
@@ -13251,7 +13406,7 @@ async function createPrStack(input, onSetupLine) {
13251
13406
  }
13252
13407
  }
13253
13408
  const claimed = new Set(threads.map((t) => t.worktreePath));
13254
- if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs27.existsSync)(bootstrap.worktreePath)) {
13409
+ if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs28.existsSync)(bootstrap.worktreePath)) {
13255
13410
  try {
13256
13411
  await removeWorktree(repoPath, bootstrap.worktreePath, {
13257
13412
  deleteBranch: bootstrap.branchName
@@ -13274,20 +13429,20 @@ function stackAgentDefaultsFrom(input) {
13274
13429
 
13275
13430
  // src/threads/adopt.ts
13276
13431
  var import_node_child_process4 = require("child_process");
13277
- var import_node_fs28 = require("fs");
13432
+ var import_node_fs29 = require("fs");
13278
13433
  var import_node_os9 = require("os");
13279
- var import_node_path23 = require("path");
13434
+ var import_node_path24 = require("path");
13280
13435
  var import_better_sqlite3 = __toESM(require("better-sqlite3"), 1);
13281
13436
  init_worktree();
13282
13437
  init_thread_store();
13283
- var CONDUCTOR_APP_SUPPORT = (0, import_node_path23.join)(
13438
+ var CONDUCTOR_APP_SUPPORT = (0, import_node_path24.join)(
13284
13439
  process.env.HOME ?? "",
13285
13440
  "Library",
13286
13441
  "Application Support",
13287
13442
  "com.conductor.app"
13288
13443
  );
13289
- var CONDUCTOR_DB = (0, import_node_path23.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
13290
- var CURSOR_SDK_STORE = (0, import_node_path23.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
13444
+ var CONDUCTOR_DB = (0, import_node_path24.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
13445
+ var CURSOR_SDK_STORE = (0, import_node_path24.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
13291
13446
  function mapAgentType(raw) {
13292
13447
  if (!raw) return null;
13293
13448
  const v = raw.toLowerCase();
@@ -13299,21 +13454,21 @@ function mapAgentType(raw) {
13299
13454
  return null;
13300
13455
  }
13301
13456
  function resolveConductorCursorAgentId(workspacePath) {
13302
- if (!workspacePath || !(0, import_node_fs28.existsSync)(CURSOR_SDK_STORE)) return null;
13457
+ if (!workspacePath || !(0, import_node_fs29.existsSync)(CURSOR_SDK_STORE)) return null;
13303
13458
  const normalized = workspacePath.replace(/\/$/, "");
13304
13459
  let best = null;
13305
13460
  let hashes;
13306
13461
  try {
13307
- hashes = (0, import_node_fs28.readdirSync)(CURSOR_SDK_STORE);
13462
+ hashes = (0, import_node_fs29.readdirSync)(CURSOR_SDK_STORE);
13308
13463
  } catch {
13309
13464
  return null;
13310
13465
  }
13311
13466
  for (const hash of hashes) {
13312
- const agentsFile = (0, import_node_path23.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
13313
- if (!(0, import_node_fs28.existsSync)(agentsFile)) continue;
13467
+ const agentsFile = (0, import_node_path24.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
13468
+ if (!(0, import_node_fs29.existsSync)(agentsFile)) continue;
13314
13469
  let text3;
13315
13470
  try {
13316
- text3 = (0, import_node_fs28.readFileSync)(agentsFile, "utf8");
13471
+ text3 = (0, import_node_fs29.readFileSync)(agentsFile, "utf8");
13317
13472
  } catch {
13318
13473
  continue;
13319
13474
  }
@@ -13337,7 +13492,7 @@ function resolveConductorCursorAgentId(workspacePath) {
13337
13492
  return best?.agentId ?? null;
13338
13493
  }
13339
13494
  async function adoptThread(input) {
13340
- if (!(0, import_node_fs28.existsSync)(input.worktreePath)) {
13495
+ if (!(0, import_node_fs29.existsSync)(input.worktreePath)) {
13341
13496
  throw new Error(`Worktree not found: ${input.worktreePath}`);
13342
13497
  }
13343
13498
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -13364,18 +13519,18 @@ function conductorDbPath() {
13364
13519
  return CONDUCTOR_DB;
13365
13520
  }
13366
13521
  function listConductorWorkspaces() {
13367
- if (!(0, import_node_fs28.existsSync)(CONDUCTOR_DB)) {
13522
+ if (!(0, import_node_fs29.existsSync)(CONDUCTOR_DB)) {
13368
13523
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
13369
13524
  }
13370
- const tmp = (0, import_node_fs28.mkdtempSync)((0, import_node_path23.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
13371
- const snapshot = (0, import_node_path23.join)(tmp, "conductor.db");
13525
+ const tmp = (0, import_node_fs29.mkdtempSync)((0, import_node_path24.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
13526
+ const snapshot = (0, import_node_path24.join)(tmp, "conductor.db");
13372
13527
  try {
13373
- (0, import_node_fs28.copyFileSync)(CONDUCTOR_DB, snapshot);
13528
+ (0, import_node_fs29.copyFileSync)(CONDUCTOR_DB, snapshot);
13374
13529
  for (const suffix of ["-wal", "-shm"]) {
13375
13530
  const src = `${CONDUCTOR_DB}${suffix}`;
13376
- if ((0, import_node_fs28.existsSync)(src)) {
13531
+ if ((0, import_node_fs29.existsSync)(src)) {
13377
13532
  try {
13378
- (0, import_node_fs28.copyFileSync)(src, `${snapshot}${suffix}`);
13533
+ (0, import_node_fs29.copyFileSync)(src, `${snapshot}${suffix}`);
13379
13534
  } catch {
13380
13535
  }
13381
13536
  }
@@ -13451,22 +13606,22 @@ function listConductorWorkspaces() {
13451
13606
  db.close();
13452
13607
  }
13453
13608
  } finally {
13454
- (0, import_node_fs28.rmSync)(tmp, { recursive: true, force: true });
13609
+ (0, import_node_fs29.rmSync)(tmp, { recursive: true, force: true });
13455
13610
  }
13456
13611
  }
13457
13612
  function importConductorWorkspace(workspaceId) {
13458
- if (!(0, import_node_fs28.existsSync)(CONDUCTOR_DB)) {
13613
+ if (!(0, import_node_fs29.existsSync)(CONDUCTOR_DB)) {
13459
13614
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
13460
13615
  }
13461
- const tmp = (0, import_node_fs28.mkdtempSync)((0, import_node_path23.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
13462
- const snapshot = (0, import_node_path23.join)(tmp, "conductor.db");
13616
+ const tmp = (0, import_node_fs29.mkdtempSync)((0, import_node_path24.join)((0, import_node_os9.tmpdir)(), "sideboard-conductor-"));
13617
+ const snapshot = (0, import_node_path24.join)(tmp, "conductor.db");
13463
13618
  try {
13464
- (0, import_node_fs28.copyFileSync)(CONDUCTOR_DB, snapshot);
13619
+ (0, import_node_fs29.copyFileSync)(CONDUCTOR_DB, snapshot);
13465
13620
  for (const suffix of ["-wal", "-shm"]) {
13466
13621
  const src = `${CONDUCTOR_DB}${suffix}`;
13467
- if ((0, import_node_fs28.existsSync)(src)) {
13622
+ if ((0, import_node_fs29.existsSync)(src)) {
13468
13623
  try {
13469
- (0, import_node_fs28.copyFileSync)(src, `${snapshot}${suffix}`);
13624
+ (0, import_node_fs29.copyFileSync)(src, `${snapshot}${suffix}`);
13470
13625
  } catch {
13471
13626
  }
13472
13627
  }
@@ -13484,7 +13639,7 @@ function importConductorWorkspace(workspaceId) {
13484
13639
  ).get(workspaceId);
13485
13640
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
13486
13641
  const worktreePath = String(row.workspacePath);
13487
- if (!(0, import_node_fs28.existsSync)(worktreePath)) {
13642
+ if (!(0, import_node_fs29.existsSync)(worktreePath)) {
13488
13643
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
13489
13644
  }
13490
13645
  let sessionId = null;
@@ -13547,7 +13702,7 @@ function importConductorWorkspace(workspaceId) {
13547
13702
  db.close();
13548
13703
  }
13549
13704
  } finally {
13550
- (0, import_node_fs28.rmSync)(tmp, { recursive: true, force: true });
13705
+ (0, import_node_fs29.rmSync)(tmp, { recursive: true, force: true });
13551
13706
  }
13552
13707
  }
13553
13708
  async function importConductorWorkspaceAsync(workspaceId) {
@@ -13558,8 +13713,8 @@ async function importConductorWorkspaceAsync(workspaceId) {
13558
13713
  var import_node_events = require("events");
13559
13714
 
13560
13715
  // src/slack/outbound-watch.ts
13561
- var import_node_fs30 = require("fs");
13562
- var import_node_path26 = require("path");
13716
+ var import_node_fs31 = require("fs");
13717
+ var import_node_path27 = require("path");
13563
13718
  init_paths();
13564
13719
  init_private_file();
13565
13720
  init_secure_file();
@@ -13605,19 +13760,19 @@ async function slackAuthTest(token) {
13605
13760
  }
13606
13761
 
13607
13762
  // src/slack/reply-target.ts
13608
- var import_node_fs29 = require("fs");
13609
- var import_node_path24 = require("path");
13763
+ var import_node_fs30 = require("fs");
13764
+ var import_node_path25 = require("path");
13610
13765
  init_paths();
13611
13766
  init_private_file();
13612
13767
  init_secure_file();
13613
13768
  function storePath2() {
13614
- return (0, import_node_path24.join)(appDataDir(), "slack-reply-to.json");
13769
+ return (0, import_node_path25.join)(appDataDir(), "slack-reply-to.json");
13615
13770
  }
13616
13771
  function readStore2() {
13617
13772
  const path2 = storePath2();
13618
- if (!(0, import_node_fs29.existsSync)(path2)) return {};
13773
+ if (!(0, import_node_fs30.existsSync)(path2)) return {};
13619
13774
  try {
13620
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs29.readFileSync)(path2, "utf8"));
13775
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs30.readFileSync)(path2, "utf8"));
13621
13776
  return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
13622
13777
  } catch {
13623
13778
  return {};
@@ -13634,11 +13789,11 @@ function getSlackReplyTarget(threadId) {
13634
13789
  }
13635
13790
 
13636
13791
  // src/slack/workspaces.ts
13637
- var import_node_path25 = require("path");
13792
+ var import_node_path26 = require("path");
13638
13793
  init_paths();
13639
13794
  init_secure_file();
13640
13795
  function storePath3() {
13641
- return (0, import_node_path25.join)(appDataDir(), "slack-workspaces.json");
13796
+ return (0, import_node_path26.join)(appDataDir(), "slack-workspaces.json");
13642
13797
  }
13643
13798
  function readStore3() {
13644
13799
  try {
@@ -13754,7 +13909,7 @@ var POLL_INTERVAL_MS = 12e3;
13754
13909
  var lastPollMs = 0;
13755
13910
  var nameCache = /* @__PURE__ */ new Map();
13756
13911
  function storePath4() {
13757
- return (0, import_node_path26.join)(appDataDir(), "slack-outbound-watch.json");
13912
+ return (0, import_node_path27.join)(appDataDir(), "slack-outbound-watch.json");
13758
13913
  }
13759
13914
  function watchId(teamId, channelId, ts) {
13760
13915
  return `${teamId}:${channelId}:${ts}`;
@@ -13784,9 +13939,9 @@ function tsNewer(a, b) {
13784
13939
  }
13785
13940
  function readStore4() {
13786
13941
  const path2 = storePath4();
13787
- if (!(0, import_node_fs30.existsSync)(path2)) return [];
13942
+ if (!(0, import_node_fs31.existsSync)(path2)) return [];
13788
13943
  try {
13789
- const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs30.readFileSync)(path2, "utf8"));
13944
+ const parsed = isSecureFileEncrypted(path2) ? readSecureJson(path2) : JSON.parse((0, import_node_fs31.readFileSync)(path2, "utf8"));
13790
13945
  return Array.isArray(parsed?.watches) ? parsed.watches : [];
13791
13946
  } catch {
13792
13947
  return [];
@@ -14131,7 +14286,7 @@ async function refreshSlackReplyBadges(opts) {
14131
14286
  }
14132
14287
 
14133
14288
  // src/orchestrator/orchestrator.ts
14134
- var import_node_fs36 = require("fs");
14289
+ var import_node_fs37 = require("fs");
14135
14290
  init_error_detail();
14136
14291
  init_agents();
14137
14292
  init_worktree();
@@ -14152,8 +14307,8 @@ function shouldAutoArchiveOnPrMerge(opts) {
14152
14307
  }
14153
14308
 
14154
14309
  // src/git/orphan-cleanup.ts
14155
- var import_node_fs31 = require("fs");
14156
- var import_node_path27 = require("path");
14310
+ var import_node_fs32 = require("fs");
14311
+ var import_node_path28 = require("path");
14157
14312
  init_worktree();
14158
14313
  init_thread_store();
14159
14314
  init_paths();
@@ -14168,9 +14323,9 @@ async function findOrphanWorktrees(repoPaths) {
14168
14323
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
14169
14324
  );
14170
14325
  const homeRoot = sideboardWorkspacesDir();
14171
- if ((0, import_node_fs31.existsSync)(homeRoot)) {
14326
+ if ((0, import_node_fs32.existsSync)(homeRoot)) {
14172
14327
  try {
14173
- for (const entry of (0, import_node_fs31.readdirSync)(homeRoot, { withFileTypes: true })) {
14328
+ for (const entry of (0, import_node_fs32.readdirSync)(homeRoot, { withFileTypes: true })) {
14174
14329
  if (!entry.isDirectory()) continue;
14175
14330
  void entry;
14176
14331
  }
@@ -14180,7 +14335,7 @@ async function findOrphanWorktrees(repoPaths) {
14180
14335
  const orphans = [];
14181
14336
  const seen = /* @__PURE__ */ new Set();
14182
14337
  for (const repoPath of repos) {
14183
- if (!repoPath || !(0, import_node_fs31.existsSync)(repoPath)) continue;
14338
+ if (!repoPath || !(0, import_node_fs32.existsSync)(repoPath)) continue;
14184
14339
  try {
14185
14340
  const wts = await listWorktrees(repoPath);
14186
14341
  for (const wt of wts) {
@@ -14191,7 +14346,7 @@ async function findOrphanWorktrees(repoPaths) {
14191
14346
  seen.add(path2);
14192
14347
  let mtimeMs = 0;
14193
14348
  try {
14194
- mtimeMs = (0, import_node_fs31.statSync)(path2).mtimeMs;
14349
+ mtimeMs = (0, import_node_fs32.statSync)(path2).mtimeMs;
14195
14350
  } catch {
14196
14351
  mtimeMs = 0;
14197
14352
  }
@@ -14201,16 +14356,16 @@ async function findOrphanWorktrees(repoPaths) {
14201
14356
  }
14202
14357
  try {
14203
14358
  const root = worktreesRoot(repoPath);
14204
- if ((0, import_node_fs31.existsSync)(root)) {
14205
- for (const entry of (0, import_node_fs31.readdirSync)(root, { withFileTypes: true })) {
14359
+ if ((0, import_node_fs32.existsSync)(root)) {
14360
+ for (const entry of (0, import_node_fs32.readdirSync)(root, { withFileTypes: true })) {
14206
14361
  if (!entry.isDirectory()) continue;
14207
- const path2 = (0, import_node_path27.join)(root, entry.name).replace(/\/$/, "");
14362
+ const path2 = (0, import_node_path28.join)(root, entry.name).replace(/\/$/, "");
14208
14363
  if (known.has(path2) || seen.has(path2)) continue;
14209
- if (!(0, import_node_fs31.existsSync)((0, import_node_path27.join)(path2, ".git"))) continue;
14364
+ if (!(0, import_node_fs32.existsSync)((0, import_node_path28.join)(path2, ".git"))) continue;
14210
14365
  seen.add(path2);
14211
14366
  let mtimeMs = 0;
14212
14367
  try {
14213
- mtimeMs = (0, import_node_fs31.statSync)(path2).mtimeMs;
14368
+ mtimeMs = (0, import_node_fs32.statSync)(path2).mtimeMs;
14214
14369
  } catch {
14215
14370
  mtimeMs = Date.now();
14216
14371
  }
@@ -14356,8 +14511,8 @@ async function applyThreadIntoMain(thread, opts) {
14356
14511
  }
14357
14512
 
14358
14513
  // src/git/clone-repo.ts
14359
- var import_node_fs32 = require("fs");
14360
- var import_node_path28 = require("path");
14514
+ var import_node_fs33 = require("fs");
14515
+ var import_node_path29 = require("path");
14361
14516
  var import_execa6 = require("execa");
14362
14517
  init_paths();
14363
14518
  init_workspaces();
@@ -14367,12 +14522,12 @@ async function cloneRepoIntoSideboard(opts) {
14367
14522
  if (!url) throw new Error("Clone URL is required");
14368
14523
  let name = opts.name?.trim();
14369
14524
  if (!name) {
14370
- const leaf = (0, import_node_path28.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
14525
+ const leaf = (0, import_node_path29.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
14371
14526
  name = leaf || "repo";
14372
14527
  }
14373
14528
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
14374
- const dest = (0, import_node_path28.join)(sideboardReposDir(), name);
14375
- if ((0, import_node_fs32.existsSync)(dest)) {
14529
+ const dest = (0, import_node_path29.join)(sideboardReposDir(), name);
14530
+ if ((0, import_node_fs33.existsSync)(dest)) {
14376
14531
  const repoPath2 = await resolveRepoRoot(dest);
14377
14532
  const workspace2 = await ensureWorkspace(repoPath2);
14378
14533
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -14394,8 +14549,8 @@ init_orchestrator_capable();
14394
14549
 
14395
14550
  // src/review/request-review.ts
14396
14551
  var import_node_crypto8 = require("crypto");
14397
- var import_node_fs33 = require("fs");
14398
- var import_node_path29 = require("path");
14552
+ var import_node_fs34 = require("fs");
14553
+ var import_node_path30 = require("path");
14399
14554
  init_global_workspace();
14400
14555
  init_thread_store();
14401
14556
 
@@ -14543,22 +14698,22 @@ function shouldRefreshReviewRequestTemplate(content) {
14543
14698
  return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
14544
14699
  }
14545
14700
  function readTextIfPresent(abs) {
14546
- if (!(0, import_node_fs33.existsSync)(abs)) return null;
14701
+ if (!(0, import_node_fs34.existsSync)(abs)) return null;
14547
14702
  try {
14548
- const content = (0, import_node_fs33.readFileSync)(abs, "utf8");
14703
+ const content = (0, import_node_fs34.readFileSync)(abs, "utf8");
14549
14704
  return content.trim() ? content : null;
14550
14705
  } catch {
14551
14706
  return null;
14552
14707
  }
14553
14708
  }
14554
14709
  function ensureAttachmentsGitignore(worktreePath) {
14555
- const gitignoreAbs = (0, import_node_path29.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
14556
- if ((0, import_node_fs33.existsSync)(gitignoreAbs)) return;
14557
- (0, import_node_fs33.mkdirSync)((0, import_node_path29.dirname)(gitignoreAbs), { recursive: true });
14558
- (0, import_node_fs33.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
14710
+ const gitignoreAbs = (0, import_node_path30.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
14711
+ if ((0, import_node_fs34.existsSync)(gitignoreAbs)) return;
14712
+ (0, import_node_fs34.mkdirSync)((0, import_node_path30.dirname)(gitignoreAbs), { recursive: true });
14713
+ (0, import_node_fs34.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
14559
14714
  }
14560
14715
  function resolveReviewGuidelines(worktreePath) {
14561
- const repoAbs = (0, import_node_path29.join)(worktreePath, REPO_REVIEW_PATH);
14716
+ const repoAbs = (0, import_node_path30.join)(worktreePath, REPO_REVIEW_PATH);
14562
14717
  const repoContent = readTextIfPresent(repoAbs);
14563
14718
  if (repoContent) {
14564
14719
  return {
@@ -14568,7 +14723,7 @@ function resolveReviewGuidelines(worktreePath) {
14568
14723
  source: "repo"
14569
14724
  };
14570
14725
  }
14571
- const localAbs = (0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH);
14726
+ const localAbs = (0, import_node_path30.join)(worktreePath, REVIEW_REQUEST_PATH);
14572
14727
  const localContent = readTextIfPresent(localAbs);
14573
14728
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
14574
14729
  return {
@@ -14578,7 +14733,7 @@ function resolveReviewGuidelines(worktreePath) {
14578
14733
  source: "local"
14579
14734
  };
14580
14735
  }
14581
- const legacyAbs = (0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
14736
+ const legacyAbs = (0, import_node_path30.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
14582
14737
  const legacyContent = readTextIfPresent(legacyAbs);
14583
14738
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
14584
14739
  return {
@@ -14589,8 +14744,8 @@ function resolveReviewGuidelines(worktreePath) {
14589
14744
  };
14590
14745
  }
14591
14746
  ensureAttachmentsGitignore(worktreePath);
14592
- (0, import_node_fs33.mkdirSync)((0, import_node_path29.dirname)(localAbs), { recursive: true });
14593
- (0, import_node_fs33.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
14747
+ (0, import_node_fs34.mkdirSync)((0, import_node_path30.dirname)(localAbs), { recursive: true });
14748
+ (0, import_node_fs34.writeFileSync)(localAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
14594
14749
  return {
14595
14750
  path: REVIEW_REQUEST_PATH,
14596
14751
  name: REVIEW_REQUEST_NAME,
@@ -14599,7 +14754,7 @@ function resolveReviewGuidelines(worktreePath) {
14599
14754
  };
14600
14755
  }
14601
14756
  function ensureReviewRequestFile(worktreePath) {
14602
- const repoAbs = (0, import_node_path29.join)(worktreePath, REPO_REVIEW_PATH);
14757
+ const repoAbs = (0, import_node_path30.join)(worktreePath, REPO_REVIEW_PATH);
14603
14758
  const repoContent = readTextIfPresent(repoAbs);
14604
14759
  if (repoContent) {
14605
14760
  return {
@@ -14609,10 +14764,10 @@ function ensureReviewRequestFile(worktreePath) {
14609
14764
  source: "repo"
14610
14765
  };
14611
14766
  }
14612
- const localAbs = (0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH);
14613
- const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
14767
+ const localAbs = (0, import_node_path30.join)(worktreePath, REVIEW_REQUEST_PATH);
14768
+ const localContent = readTextIfPresent(localAbs) ?? readTextIfPresent((0, import_node_path30.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
14614
14769
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
14615
- const path2 = (0, import_node_fs33.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
14770
+ const path2 = (0, import_node_fs34.existsSync)(localAbs) ? REVIEW_REQUEST_PATH : LEGACY_REVIEW_REQUEST_PATH;
14616
14771
  return {
14617
14772
  path: path2,
14618
14773
  name: REVIEW_REQUEST_NAME,
@@ -14620,8 +14775,8 @@ function ensureReviewRequestFile(worktreePath) {
14620
14775
  source: "local"
14621
14776
  };
14622
14777
  }
14623
- (0, import_node_fs33.mkdirSync)((0, import_node_path29.dirname)(repoAbs), { recursive: true });
14624
- (0, import_node_fs33.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
14778
+ (0, import_node_fs34.mkdirSync)((0, import_node_path30.dirname)(repoAbs), { recursive: true });
14779
+ (0, import_node_fs34.writeFileSync)(repoAbs, REVIEW_REQUEST_TEMPLATE, "utf8");
14625
14780
  return {
14626
14781
  path: REPO_REVIEW_PATH,
14627
14782
  name: REPO_REVIEW_NAME,
@@ -14641,7 +14796,7 @@ function buildReviewRequestAttachment(content, opts) {
14641
14796
  };
14642
14797
  }
14643
14798
  function readExistingReviewRequestFile(worktreePath) {
14644
- return readTextIfPresent((0, import_node_path29.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path29.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path29.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
14799
+ return readTextIfPresent((0, import_node_path30.join)(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent((0, import_node_path30.join)(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent((0, import_node_path30.join)(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
14645
14800
  }
14646
14801
  async function requestReview(threadRef, send2) {
14647
14802
  const from = findThreadByRef(threadRef);
@@ -14902,7 +15057,7 @@ var Orchestrator = class {
14902
15057
  }
14903
15058
  continue;
14904
15059
  }
14905
- if (!(0, import_node_fs36.existsSync)(thread.worktreePath)) {
15060
+ if (!(0, import_node_fs37.existsSync)(thread.worktreePath)) {
14906
15061
  setStatus(thread.id, "broken", "Worktree missing on disk");
14907
15062
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
14908
15063
  continue;
@@ -15077,14 +15232,7 @@ var Orchestrator = class {
15077
15232
  return thread;
15078
15233
  }
15079
15234
  async finishCreateThread(threadId, prompt) {
15080
- await this.runSetupAfterCreate(threadId);
15081
- const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
15082
- if (autoRunAfterSetupEnabled2()) {
15083
- try {
15084
- await this.startDev(threadId);
15085
- } catch {
15086
- }
15087
- }
15235
+ const setup = this.runSetupAfterCreate(threadId);
15088
15236
  if (prompt) {
15089
15237
  try {
15090
15238
  await this.send(threadId, prompt);
@@ -15095,6 +15243,14 @@ var Orchestrator = class {
15095
15243
  });
15096
15244
  }
15097
15245
  }
15246
+ await setup;
15247
+ const { autoRunAfterSetupEnabled: autoRunAfterSetupEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
15248
+ if (autoRunAfterSetupEnabled2()) {
15249
+ try {
15250
+ await this.startDev(threadId);
15251
+ } catch {
15252
+ }
15253
+ }
15098
15254
  }
15099
15255
  /** Run workspace setup after a new worktree is created (no-op if none configured). */
15100
15256
  async runSetupAfterCreate(threadId) {
@@ -15792,7 +15948,7 @@ var Orchestrator = class {
15792
15948
  });
15793
15949
  this.emit({ type: "setup_started", threadId: thread.id });
15794
15950
  try {
15795
- let setup = await runSetupScript(
15951
+ const setup = await runWorkspaceSetup(
15796
15952
  thread.repoPath,
15797
15953
  thread.worktreePath,
15798
15954
  (line) => {
@@ -15800,18 +15956,9 @@ var Orchestrator = class {
15800
15956
  },
15801
15957
  { signal: abort.signal }
15802
15958
  );
15803
- if (!setup.ran) {
15804
- setup = await runCursorWorktreeSetup(
15805
- thread.repoPath,
15806
- thread.worktreePath,
15807
- (line) => {
15808
- this.emit({ type: "setup_output", threadId: thread.id, line });
15809
- }
15810
- );
15811
- }
15812
15959
  if (!setup.ran) {
15813
15960
  throw new Error(
15814
- "No setup script in .sideboard/settings.toml, .conductor/settings.toml, or .cursor/worktrees.json"
15961
+ "No setup script in .sideboard/settings.toml, .conductor/settings.toml, .cursor/worktrees.json, or script/setup (bin/setup, scripts/setup)"
15815
15962
  );
15816
15963
  }
15817
15964
  if (setup.exitCode !== 0 && setup.exitCode !== null) {
@@ -16119,7 +16266,7 @@ var Orchestrator = class {
16119
16266
  this.emit({ type: "status_changed", threadId: t.id, status: t.status });
16120
16267
  }
16121
16268
  for (const id of result.createdThreadIds) {
16122
- await this.runSetupAfterCreate(id);
16269
+ void this.runSetupAfterCreate(id);
16123
16270
  }
16124
16271
  return { stack: result.stack, threads: result.threads };
16125
16272
  }
@@ -16136,7 +16283,7 @@ var Orchestrator = class {
16136
16283
  status: result.thread.status
16137
16284
  });
16138
16285
  if (result.createdWorktree) {
16139
- await this.runSetupAfterCreate(result.thread.id);
16286
+ void this.runSetupAfterCreate(result.thread.id);
16140
16287
  }
16141
16288
  return { stack: result.stack, thread: result.thread };
16142
16289
  }
@@ -16151,7 +16298,7 @@ var Orchestrator = class {
16151
16298
  this.emit({ type: "status_changed", threadId: t.id, status: t.status });
16152
16299
  }
16153
16300
  for (const id of result.createdThreadIds) {
16154
- await this.runSetupAfterCreate(id);
16301
+ void this.runSetupAfterCreate(id);
16155
16302
  }
16156
16303
  return { stack: result.stack, threads: result.threads };
16157
16304
  }
@@ -16162,7 +16309,7 @@ var Orchestrator = class {
16162
16309
  this.emit({ type: "status_changed", threadId: t.id, status: t.status });
16163
16310
  }
16164
16311
  for (const id of result.createdThreadIds) {
16165
- await this.runSetupAfterCreate(id);
16312
+ void this.runSetupAfterCreate(id);
16166
16313
  }
16167
16314
  return { stack: result.stack, threads: result.threads };
16168
16315
  }
@@ -16293,7 +16440,7 @@ var Orchestrator = class {
16293
16440
  async forkThreadWorktree(input) {
16294
16441
  const thread = await forkThreadWorktree(input);
16295
16442
  this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
16296
- await this.runSetupAfterCreate(thread.id);
16443
+ void this.runSetupAfterCreate(thread.id);
16297
16444
  return thread;
16298
16445
  }
16299
16446
  renameThread(threadRef, title) {
@@ -16396,7 +16543,7 @@ var Orchestrator = class {
16396
16543
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
16397
16544
  return restored2;
16398
16545
  }
16399
- if (!(0, import_node_fs36.existsSync)(thread.worktreePath)) {
16546
+ if (!(0, import_node_fs37.existsSync)(thread.worktreePath)) {
16400
16547
  const { createThreadWorktree: createThreadWorktree2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
16401
16548
  const { execa: execa7 } = await import("execa");
16402
16549
  const slug = thread.worktreePath.split("/").pop();
@@ -16501,7 +16648,7 @@ async function startOrchestration(opts) {
16501
16648
  planMode: opts.planMode,
16502
16649
  attachments: opts.attachments
16503
16650
  };
16504
- const thread = await createThread({
16651
+ const thread = await orch.createThread({
16505
16652
  sourceType: "branch",
16506
16653
  sourceRef: "default",
16507
16654
  ...createOpts
@@ -16509,7 +16656,7 @@ async function startOrchestration(opts) {
16509
16656
  const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await Promise.resolve().then(() => (init_worktree(), worktree_exports));
16510
16657
  const repo = await resolveRepoRoot2(repoPath);
16511
16658
  const def = await resolveDefaultBranch2(repo);
16512
- return createThread({
16659
+ return orch.createThread({
16513
16660
  sourceType: "branch",
16514
16661
  sourceRef: def,
16515
16662
  ...createOpts,
@@ -16637,7 +16784,7 @@ init_coordinator_prompt();
16637
16784
  var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
16638
16785
  var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
16639
16786
  var import_zod3 = require("zod");
16640
- var import_node_path32 = require("path");
16787
+ var import_node_path33 = require("path");
16641
16788
  init_worktree();
16642
16789
  init_global_workspace();
16643
16790
  init_list_models();
@@ -17315,7 +17462,7 @@ async function startMcpServer() {
17315
17462
  async () => {
17316
17463
  const threads = orch.getThreads(true);
17317
17464
  const lines = threads.map((t) => {
17318
- const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path32.basename)(t.repoPath) || t.repoPath;
17465
+ const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path33.basename)(t.repoPath) || t.repoPath;
17319
17466
  return `${t.id.slice(0, 8)} ${t.status.padEnd(9)} ${t.agent.padEnd(8)} ${repo} ${t.sourceType}:${t.sourceRef} ${t.title} sideboard://thread/${t.id}${t.devPort ? ` http://localhost:${t.devPort}` : ""}`;
17320
17467
  });
17321
17468
  return {
@@ -17526,7 +17673,7 @@ async function startMcpServer() {
17526
17673
  );
17527
17674
  server.tool(
17528
17675
  "create_thread",
17529
- `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.`,
17676
+ `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.`,
17530
17677
  {
17531
17678
  sourceType: import_zod3.z.enum(["branch", "pr", "ticket"]),
17532
17679
  sourceRef: import_zod3.z.string(),
@@ -18044,7 +18191,7 @@ async function startMcpServer() {
18044
18191
  );
18045
18192
  server.tool(
18046
18193
  "run_setup",
18047
- "Re-run workspace setup (Sideboard/Conductor settings or .cursor/worktrees.json)",
18194
+ "Re-run workspace setup (Sideboard/Conductor settings, .cursor/worktrees.json, or script/setup). New worktrees already run this automatically.",
18048
18195
  { ref: import_zod3.z.string() },
18049
18196
  async ({ ref }) => {
18050
18197
  const result = await orch.runSetup(ref);
@@ -19929,9 +20076,9 @@ var import_node_http3 = require("http");
19929
20076
  var import_ws3 = require("ws");
19930
20077
 
19931
20078
  // src/slack/relay-static.ts
19932
- var import_node_fs37 = require("fs");
20079
+ var import_node_fs38 = require("fs");
19933
20080
  var import_promises = require("fs/promises");
19934
- var import_node_path33 = __toESM(require("path"), 1);
20081
+ var import_node_path34 = __toESM(require("path"), 1);
19935
20082
  var TYPES = {
19936
20083
  ".css": "text/css; charset=utf-8",
19937
20084
  ".html": "text/html; charset=utf-8",
@@ -19962,9 +20109,9 @@ function resolveStaticPath(root, requestUrl) {
19962
20109
  return null;
19963
20110
  }
19964
20111
  if (!pathname.startsWith("/") || pathname.includes("\0")) return null;
19965
- const rootResolved = import_node_path33.default.resolve(root);
19966
- const candidate = import_node_path33.default.resolve(rootResolved, `.${pathname}`);
19967
- if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path33.default.sep)) {
20112
+ const rootResolved = import_node_path34.default.resolve(root);
20113
+ const candidate = import_node_path34.default.resolve(rootResolved, `.${pathname}`);
20114
+ if (candidate !== rootResolved && !candidate.startsWith(rootResolved + import_node_path34.default.sep)) {
19968
20115
  return null;
19969
20116
  }
19970
20117
  return candidate;
@@ -19978,7 +20125,7 @@ async function fileSize(file) {
19978
20125
  }
19979
20126
  }
19980
20127
  function sendFile(req, res, file, size) {
19981
- const ext = import_node_path33.default.extname(file).toLowerCase();
20128
+ const ext = import_node_path34.default.extname(file).toLowerCase();
19982
20129
  res.writeHead(200, {
19983
20130
  "Content-Type": TYPES[ext] ?? "application/octet-stream",
19984
20131
  "Content-Length": size,
@@ -19988,7 +20135,7 @@ function sendFile(req, res, file, size) {
19988
20135
  res.end();
19989
20136
  return true;
19990
20137
  }
19991
- (0, import_node_fs37.createReadStream)(file).pipe(res);
20138
+ (0, import_node_fs38.createReadStream)(file).pipe(res);
19992
20139
  return true;
19993
20140
  }
19994
20141
  async function tryServeStatic(req, res, root) {
@@ -19997,7 +20144,7 @@ async function tryServeStatic(req, res, root) {
19997
20144
  if (!candidate) return false;
19998
20145
  const direct = await fileSize(candidate);
19999
20146
  if (direct != null) return sendFile(req, res, candidate, direct);
20000
- const asIndex = import_node_path33.default.join(candidate, "index.html");
20147
+ const asIndex = import_node_path34.default.join(candidate, "index.html");
20001
20148
  const indexSize = await fileSize(asIndex);
20002
20149
  if (indexSize != null) return sendFile(req, res, asIndex, indexSize);
20003
20150
  return false;
@@ -20229,6 +20376,7 @@ async function startSlackRelayServer(opts) {
20229
20376
  CONTEXT_KEEP_RECENT_CHARS,
20230
20377
  CONTEXT_KEEP_RECENT_MESSAGES,
20231
20378
  CONTEXT_MIN_MESSAGES,
20379
+ CONVENTION_SETUP_RELPATHS,
20232
20380
  COORDINATOR_TOOL_PLAYBOOK,
20233
20381
  FAMOUS_SOCCER_TEAMS,
20234
20382
  GITHUB_GIT_AUTH_MODES,
@@ -20390,6 +20538,7 @@ async function startSlackRelayServer(opts) {
20390
20538
  extractiveSummary,
20391
20539
  fetchPrHead,
20392
20540
  finalizeParts,
20541
+ findConventionSetup,
20393
20542
  findInvalidCacheControlTtlOrder,
20394
20543
  findOrphanWorktrees,
20395
20544
  findThreadByRef,
@@ -20461,6 +20610,7 @@ async function startSlackRelayServer(opts) {
20461
20610
  hasBakedLinearOAuth,
20462
20611
  hasBakedSlackOAuth,
20463
20612
  hasConductorHook,
20613
+ hasConventionSetup,
20464
20614
  hasCursorWorktreeSetup,
20465
20615
  hasRepoHook,
20466
20616
  hasWorkspaceHook,
@@ -20636,10 +20786,12 @@ async function startSlackRelayServer(opts) {
20636
20786
  run,
20637
20787
  runArchiveScript,
20638
20788
  runCloudConnect,
20789
+ runConventionSetup,
20639
20790
  runCursorWorktreeSetup,
20640
20791
  runSetupScript,
20641
20792
  runSlackListen,
20642
20793
  runSlackRelayClient,
20794
+ runWorkspaceSetup,
20643
20795
  sameWorktreePath,
20644
20796
  sanitizeMcpServerName,
20645
20797
  saveAppSettings,