@sideboard-ai/core 0.1.227 → 0.1.229

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 (44) hide show
  1. package/dist/{abletime-D6773P33.js → abletime-BGVOCEOU.js} +4 -4
  2. package/dist/{abletime-BF253OZT.js → abletime-WZNDTRVL.js} +4 -4
  3. package/dist/{abletime-oauth-KQPVVBKA.js → abletime-oauth-6M5GWEPX.js} +3 -3
  4. package/dist/{abletime-oauth-H4672PRH.js → abletime-oauth-ZLU2EYRK.js} +3 -3
  5. package/dist/{abletime-rest-DAFPXZ7H.js → abletime-rest-F7XG5NGY.js} +3 -3
  6. package/dist/{abletime-rest-OPEVV3XC.js → abletime-rest-WNHIATB3.js} +3 -3
  7. package/dist/{agents-DV5UROWB.js → agents-B7G4BQTS.js} +4 -4
  8. package/dist/{agents-QQ77D7VT.js → agents-ZKP7QNXA.js} +4 -4
  9. package/dist/{app-settings-5RQMQKSB.js → app-settings-KBL2G7M4.js} +7 -1
  10. package/dist/{app-settings-V2BBCX2H.js → app-settings-UXWCPDEA.js} +7 -1
  11. package/dist/{chunk-FUDJ6NFM.js → chunk-6HKGCUDN.js} +117 -62
  12. package/dist/{chunk-N2VST3NL.js → chunk-7YKXBFQE.js} +2 -2
  13. package/dist/{chunk-KTZESHYH.js → chunk-AMMRFFB7.js} +1 -1
  14. package/dist/{chunk-HSYE5ID6.js → chunk-AS4UN7QL.js} +5 -5
  15. package/dist/{chunk-3NWUHXU3.js → chunk-C774RJJA.js} +3 -3
  16. package/dist/{chunk-NFWPDEN4.js → chunk-F3GT6DQW.js} +1 -1
  17. package/dist/{chunk-CLI5DVU4.js → chunk-GHRZNPBK.js} +2 -2
  18. package/dist/{chunk-EWHJNJHV.js → chunk-I5NC7DWO.js} +38 -0
  19. package/dist/{chunk-VUW3VKLW.js → chunk-LULHFLPU.js} +17 -4
  20. package/dist/{chunk-646I442S.js → chunk-MVLXDYN5.js} +5 -5
  21. package/dist/{chunk-P2EAAM3H.js → chunk-N7UXGM3Y.js} +2 -2
  22. package/dist/{chunk-RRW2XWAY.js → chunk-P6ZM5QJW.js} +2 -2
  23. package/dist/{chunk-THLVCXLF.js → chunk-RGNPPRZZ.js} +3 -3
  24. package/dist/{chunk-Y5JES2VV.js → chunk-RZTRWN2V.js} +38 -0
  25. package/dist/{chunk-SOGGKYFV.js → chunk-SWNEA5OZ.js} +3 -3
  26. package/dist/{chunk-SQHRPJ7P.js → chunk-T7Y5ULHM.js} +14 -4
  27. package/dist/{chunk-I2HOATRJ.js → chunk-UHT6OS7V.js} +129 -62
  28. package/dist/{coordinator-prompt-JLMQVORO.js → coordinator-prompt-DZMMCDRW.js} +3 -3
  29. package/dist/{coordinator-prompt-VZ7OSRLD.js → coordinator-prompt-RL3GKIAQ.js} +3 -3
  30. package/dist/{global-workspace-QPSJEXGR.js → global-workspace-G3QEVRGZ.js} +3 -3
  31. package/dist/{global-workspace-3FDAUNN2.js → global-workspace-QW4OXCLJ.js} +3 -3
  32. package/dist/index.cjs +927 -658
  33. package/dist/index.d.cts +89 -3
  34. package/dist/index.d.ts +89 -3
  35. package/dist/index.js +206 -67
  36. package/dist/mcp/run-stdio.cjs +224 -84
  37. package/dist/mcp/run-stdio.js +86 -50
  38. package/dist/{orchestrator-CWOSAYAE.js → orchestrator-GKAHLGXT.js} +5 -5
  39. package/dist/{orchestrator-VKPHI64Q.js → orchestrator-X4VFA5WW.js} +5 -5
  40. package/dist/{workspaces-76W7IEKR.js → workspaces-77C5XQEY.js} +3 -3
  41. package/dist/{workspaces-TDBA64II.js → workspaces-WXRPLT2N.js} +3 -3
  42. package/dist/{worktree-I573UOPD.js → worktree-L6FJXFUC.js} +2 -2
  43. package/dist/{worktree-7V67XTEO.js → worktree-P67WAJKH.js} +2 -2
  44. package/package.json +1 -1
@@ -15,11 +15,11 @@ import {
15
15
  toAbleTimeIssueInfo,
16
16
  updateAbleTimeTask,
17
17
  verifyAbleTimeConnection
18
- } from "./chunk-SOGGKYFV.js";
19
- import "./chunk-RRW2XWAY.js";
20
- import "./chunk-646I442S.js";
18
+ } from "./chunk-SWNEA5OZ.js";
19
+ import "./chunk-P6ZM5QJW.js";
20
+ import "./chunk-MVLXDYN5.js";
21
21
  import "./chunk-N7WZ6NIN.js";
22
- import "./chunk-EWHJNJHV.js";
22
+ import "./chunk-I5NC7DWO.js";
23
23
  import "./chunk-WDRMZKVB.js";
24
24
  import "./chunk-JT7R45JB.js";
25
25
  import "./chunk-77WWLBCI.js";
@@ -17,11 +17,11 @@ import {
17
17
  toAbleTimeIssueInfo,
18
18
  updateAbleTimeTask,
19
19
  verifyAbleTimeConnection
20
- } from "./chunk-THLVCXLF.js";
21
- import "./chunk-CLI5DVU4.js";
22
- import "./chunk-HSYE5ID6.js";
20
+ } from "./chunk-RGNPPRZZ.js";
21
+ import "./chunk-GHRZNPBK.js";
22
+ import "./chunk-AS4UN7QL.js";
23
23
  import "./chunk-VKQGAWHY.js";
24
- import "./chunk-Y5JES2VV.js";
24
+ import "./chunk-RZTRWN2V.js";
25
25
  import "./chunk-NSTQ6QKD.js";
26
26
  import "./chunk-KGZBYWZ3.js";
27
27
  import "./chunk-EQNRWDLN.js";
@@ -20,10 +20,10 @@ import {
20
20
  parseAbleTimeOAuthCallbackUrl,
21
21
  resolveAbleTimeOAuthHost,
22
22
  startAbleTimeOAuth
23
- } from "./chunk-3NWUHXU3.js";
24
- import "./chunk-646I442S.js";
23
+ } from "./chunk-C774RJJA.js";
24
+ import "./chunk-MVLXDYN5.js";
25
25
  import "./chunk-N7WZ6NIN.js";
26
- import "./chunk-EWHJNJHV.js";
26
+ import "./chunk-I5NC7DWO.js";
27
27
  import "./chunk-WDRMZKVB.js";
28
28
  import "./chunk-JT7R45JB.js";
29
29
  import "./chunk-77WWLBCI.js";
@@ -3,7 +3,7 @@
3
3
  import {
4
4
  DEFAULT_ABLETIME_HOST,
5
5
  normalizeAbleTimeHost
6
- } from "./chunk-HSYE5ID6.js";
6
+ } from "./chunk-AS4UN7QL.js";
7
7
  import {
8
8
  httpFetch
9
9
  } from "./chunk-VKQGAWHY.js";
@@ -12,7 +12,7 @@ import {
12
12
  getAbleTimeHost,
13
13
  loadAppSettings,
14
14
  saveAbleTimeConnection
15
- } from "./chunk-Y5JES2VV.js";
15
+ } from "./chunk-RZTRWN2V.js";
16
16
  import "./chunk-NSTQ6QKD.js";
17
17
  import "./chunk-KGZBYWZ3.js";
18
18
  import "./chunk-EQNRWDLN.js";
@@ -287,7 +287,7 @@ async function startAbleTimeOAuth(opts) {
287
287
  persistAbleTimeTokens(data, { host });
288
288
  const token = data.access_token.trim();
289
289
  try {
290
- const { getAbleTimeOrientation } = await import("./abletime-BF253OZT.js");
290
+ const { getAbleTimeOrientation } = await import("./abletime-WZNDTRVL.js");
291
291
  const orientation = await getAbleTimeOrientation({ token, host });
292
292
  return saveAbleTimeConnection({
293
293
  accessToken: token,
@@ -5,10 +5,10 @@ import {
5
5
  callAbleTimeRestTool,
6
6
  looksLikeAbleTimeUlid,
7
7
  textFromAbleTimeDoc
8
- } from "./chunk-RRW2XWAY.js";
9
- import "./chunk-646I442S.js";
8
+ } from "./chunk-P6ZM5QJW.js";
9
+ import "./chunk-MVLXDYN5.js";
10
10
  import "./chunk-N7WZ6NIN.js";
11
- import "./chunk-EWHJNJHV.js";
11
+ import "./chunk-I5NC7DWO.js";
12
12
  import "./chunk-WDRMZKVB.js";
13
13
  import "./chunk-JT7R45JB.js";
14
14
  import "./chunk-77WWLBCI.js";
@@ -7,10 +7,10 @@ import {
7
7
  callAbleTimeRestTool,
8
8
  looksLikeAbleTimeUlid,
9
9
  textFromAbleTimeDoc
10
- } from "./chunk-CLI5DVU4.js";
11
- import "./chunk-HSYE5ID6.js";
10
+ } from "./chunk-GHRZNPBK.js";
11
+ import "./chunk-AS4UN7QL.js";
12
12
  import "./chunk-VKQGAWHY.js";
13
- import "./chunk-Y5JES2VV.js";
13
+ import "./chunk-RZTRWN2V.js";
14
14
  import "./chunk-NSTQ6QKD.js";
15
15
  import "./chunk-KGZBYWZ3.js";
16
16
  import "./chunk-EQNRWDLN.js";
@@ -50,12 +50,12 @@ import {
50
50
  resolveQuotaFallbackAgent,
51
51
  turnCostUsdFromCursorUsage,
52
52
  whichOnPath
53
- } from "./chunk-SQHRPJ7P.js";
54
- import "./chunk-P2EAAM3H.js";
53
+ } from "./chunk-T7Y5ULHM.js";
54
+ import "./chunk-N7UXGM3Y.js";
55
55
  import "./chunk-SXFRXNBM.js";
56
56
  import "./chunk-P2BSMNHB.js";
57
57
  import "./chunk-VKQGAWHY.js";
58
- import "./chunk-NFWPDEN4.js";
58
+ import "./chunk-F3GT6DQW.js";
59
59
  import "./chunk-D6JWYJ4P.js";
60
60
  import "./chunk-HY2GFZ5S.js";
61
61
  import "./chunk-X5B3OS5I.js";
@@ -74,7 +74,7 @@ import {
74
74
  assertOrchestratorCapableAgent,
75
75
  coerceOrchestratorAgent,
76
76
  isOrchestratorCapableAgent
77
- } from "./chunk-Y5JES2VV.js";
77
+ } from "./chunk-RZTRWN2V.js";
78
78
  import "./chunk-NSTQ6QKD.js";
79
79
  import "./chunk-KGZBYWZ3.js";
80
80
  import "./chunk-EQNRWDLN.js";
@@ -44,9 +44,9 @@ import {
44
44
  resolveLoginCommand,
45
45
  resolveQuotaFallbackAgent,
46
46
  whichOnPath
47
- } from "./chunk-VUW3VKLW.js";
48
- import "./chunk-N2VST3NL.js";
49
- import "./chunk-KTZESHYH.js";
47
+ } from "./chunk-LULHFLPU.js";
48
+ import "./chunk-7YKXBFQE.js";
49
+ import "./chunk-AMMRFFB7.js";
50
50
  import "./chunk-6K64FJDD.js";
51
51
  import "./chunk-PO4M4JAJ.js";
52
52
  import "./chunk-ZXJMAKEP.js";
@@ -63,7 +63,7 @@ import {
63
63
  assertOrchestratorCapableAgent,
64
64
  coerceOrchestratorAgent,
65
65
  isOrchestratorCapableAgent
66
- } from "./chunk-EWHJNJHV.js";
66
+ } from "./chunk-I5NC7DWO.js";
67
67
  import "./chunk-WDRMZKVB.js";
68
68
  import "./chunk-JT7R45JB.js";
69
69
  import "./chunk-3IMSQNTS.js";
@@ -1,12 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import {
4
+ AGENT_DONE_SOUNDS,
4
5
  FOLLOW_UP_BEHAVIORS,
5
6
  GITHUB_GIT_AUTH_MODES,
6
7
  HARNESS_ENV_KEYS,
7
8
  ISSUE_SOURCE_LABELS,
8
9
  PROFILE_NOTES_MAX,
9
10
  USAGE_ON_LIMIT_VALUES,
11
+ agentDoneSound,
10
12
  appSettingsPath,
11
13
  applyAppEnvironment,
12
14
  autoArchiveOnMergeEnabled,
@@ -54,6 +56,7 @@ import {
54
56
  historyMaxCount,
55
57
  historyMaxDays,
56
58
  isAbleTimeConnected,
59
+ isAgentDoneSound,
57
60
  isIssueSourceConnected,
58
61
  isLinearConnected,
59
62
  isUsageOnLimit,
@@ -94,19 +97,21 @@ import {
94
97
  updateProjectProfileSettings,
95
98
  usageOnLimit,
96
99
  writeViewerContext
97
- } from "./chunk-Y5JES2VV.js";
100
+ } from "./chunk-RZTRWN2V.js";
98
101
  import "./chunk-NSTQ6QKD.js";
99
102
  import "./chunk-KGZBYWZ3.js";
100
103
  import "./chunk-EQNRWDLN.js";
101
104
  import "./chunk-WWUABK6B.js";
102
105
  import "./chunk-FJZWM2ON.js";
103
106
  export {
107
+ AGENT_DONE_SOUNDS,
104
108
  FOLLOW_UP_BEHAVIORS,
105
109
  GITHUB_GIT_AUTH_MODES,
106
110
  HARNESS_ENV_KEYS,
107
111
  ISSUE_SOURCE_LABELS,
108
112
  PROFILE_NOTES_MAX,
109
113
  USAGE_ON_LIMIT_VALUES,
114
+ agentDoneSound,
110
115
  appSettingsPath,
111
116
  applyAppEnvironment,
112
117
  autoArchiveOnMergeEnabled,
@@ -154,6 +159,7 @@ export {
154
159
  historyMaxCount,
155
160
  historyMaxDays,
156
161
  isAbleTimeConnected,
162
+ isAgentDoneSound,
157
163
  isIssueSourceConnected,
158
164
  isLinearConnected,
159
165
  isUsageOnLimit,
@@ -1,10 +1,12 @@
1
1
  import {
2
+ AGENT_DONE_SOUNDS,
2
3
  FOLLOW_UP_BEHAVIORS,
3
4
  GITHUB_GIT_AUTH_MODES,
4
5
  HARNESS_ENV_KEYS,
5
6
  ISSUE_SOURCE_LABELS,
6
7
  PROFILE_NOTES_MAX,
7
8
  USAGE_ON_LIMIT_VALUES,
9
+ agentDoneSound,
8
10
  appSettingsPath,
9
11
  applyAppEnvironment,
10
12
  autoArchiveOnMergeEnabled,
@@ -52,6 +54,7 @@ import {
52
54
  historyMaxCount,
53
55
  historyMaxDays,
54
56
  isAbleTimeConnected,
57
+ isAgentDoneSound,
55
58
  isIssueSourceConnected,
56
59
  isLinearConnected,
57
60
  isUsageOnLimit,
@@ -92,19 +95,21 @@ import {
92
95
  updateProjectProfileSettings,
93
96
  usageOnLimit,
94
97
  writeViewerContext
95
- } from "./chunk-EWHJNJHV.js";
98
+ } from "./chunk-I5NC7DWO.js";
96
99
  import "./chunk-WDRMZKVB.js";
97
100
  import "./chunk-JT7R45JB.js";
98
101
  import "./chunk-77WWLBCI.js";
99
102
  import "./chunk-WFUDY6PC.js";
100
103
  import "./chunk-4TR3HZFT.js";
101
104
  export {
105
+ AGENT_DONE_SOUNDS,
102
106
  FOLLOW_UP_BEHAVIORS,
103
107
  GITHUB_GIT_AUTH_MODES,
104
108
  HARNESS_ENV_KEYS,
105
109
  ISSUE_SOURCE_LABELS,
106
110
  PROFILE_NOTES_MAX,
107
111
  USAGE_ON_LIMIT_VALUES,
112
+ agentDoneSound,
108
113
  appSettingsPath,
109
114
  applyAppEnvironment,
110
115
  autoArchiveOnMergeEnabled,
@@ -152,6 +157,7 @@ export {
152
157
  historyMaxCount,
153
158
  historyMaxDays,
154
159
  isAbleTimeConnected,
160
+ isAgentDoneSound,
155
161
  isIssueSourceConnected,
156
162
  isLinearConnected,
157
163
  isUsageOnLimit,
@@ -42,7 +42,7 @@ import {
42
42
  summarizeTurnStderr,
43
43
  toolDescription,
44
44
  turnFailChatText
45
- } from "./chunk-SQHRPJ7P.js";
45
+ } from "./chunk-T7Y5ULHM.js";
46
46
  import {
47
47
  SLACK_REPLY_FORMATTING,
48
48
  addWorkspace,
@@ -65,7 +65,7 @@ import {
65
65
  stageAbsolutePathsAsAttachments,
66
66
  stageBuffersAsAttachments,
67
67
  syncWorkspacesFromThreads
68
- } from "./chunk-P2EAAM3H.js";
68
+ } from "./chunk-N7UXGM3Y.js";
69
69
  import {
70
70
  addPrStackLayer,
71
71
  allocateTeamName,
@@ -114,7 +114,7 @@ import {
114
114
  worktreeDisplayLabelForGroup,
115
115
  worktreeNameFromPath,
116
116
  worktreeSlugForTicket
117
- } from "./chunk-NFWPDEN4.js";
117
+ } from "./chunk-F3GT6DQW.js";
118
118
  import {
119
119
  ATTACHMENTS_DIR,
120
120
  DETACHED_JOBS_DIR,
@@ -177,7 +177,7 @@ import {
177
177
  updateAdvancedSettings,
178
178
  usageOnLimit,
179
179
  writeSecureJson
180
- } from "./chunk-Y5JES2VV.js";
180
+ } from "./chunk-RZTRWN2V.js";
181
181
  import {
182
182
  writePrivateFile
183
183
  } from "./chunk-NSTQ6QKD.js";
@@ -418,7 +418,7 @@ async function continueSourceThread(threadId, prompt) {
418
418
  await continueOnReply(threadId, prompt);
419
419
  return;
420
420
  }
421
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-CWOSAYAE.js");
421
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-GKAHLGXT.js");
422
422
  await getOrchestrator2().send(threadId, prompt);
423
423
  } catch {
424
424
  }
@@ -895,9 +895,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
895
895
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
896
896
  );
897
897
  }
898
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-QPSJEXGR.js");
898
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-G3QEVRGZ.js");
899
899
  if (isGlobalThread2(thread)) {
900
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-VZ7OSRLD.js");
900
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-RL3GKIAQ.js");
901
901
  ensureGlobalCoordinatorCwd2(
902
902
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
903
903
  );
@@ -2379,61 +2379,92 @@ function getRunScript(worktreePath, repoPath, name) {
2379
2379
  function getRunMode(worktreePath, repoPath) {
2380
2380
  return loadWorkspaceSettings(worktreePath, repoPath)?.runMode ?? "concurrent";
2381
2381
  }
2382
- async function allocatePort() {
2382
+ async function reservePort() {
2383
2383
  return new Promise((resolve, reject) => {
2384
2384
  const server = createServer();
2385
+ let released = false;
2386
+ const release = () => new Promise((res) => {
2387
+ if (released) {
2388
+ res();
2389
+ return;
2390
+ }
2391
+ released = true;
2392
+ server.close(() => res());
2393
+ });
2385
2394
  server.listen(0, "127.0.0.1", () => {
2386
2395
  const addr = server.address();
2387
2396
  if (!addr || typeof addr === "string") {
2388
- server.close();
2389
- reject(new Error("Failed to allocate port"));
2397
+ void release().then(() => reject(new Error("Failed to allocate port")));
2390
2398
  return;
2391
2399
  }
2392
- const port = addr.port;
2393
- server.close((err) => err ? reject(err) : resolve(port));
2400
+ resolve({ port: addr.port, release });
2394
2401
  });
2395
2402
  server.on("error", reject);
2396
2403
  });
2397
2404
  }
2398
- async function allocatePortRange(size = PORT_RANGE_SIZE) {
2399
- const base = await allocatePort();
2400
- const ports = [base];
2401
- for (let i = 1; i < size; i++) {
2402
- const candidate = base + i;
2403
- const free = await new Promise((resolve) => {
2404
- const server = createServer();
2405
- server.once("error", () => resolve(false));
2406
- server.listen(candidate, "127.0.0.1", () => {
2407
- server.close(() => resolve(true));
2408
- });
2405
+ async function tryReservePort(port) {
2406
+ return new Promise((resolve) => {
2407
+ const server = createServer();
2408
+ let released = false;
2409
+ const release = () => new Promise((res) => {
2410
+ if (released) {
2411
+ res();
2412
+ return;
2413
+ }
2414
+ released = true;
2415
+ server.close(() => res());
2409
2416
  });
2410
- if (free) {
2411
- ports.push(candidate);
2412
- } else {
2413
- ports.push(await allocatePort());
2417
+ server.once("error", () => resolve(null));
2418
+ server.listen(port, "127.0.0.1", () => {
2419
+ resolve({ port, release });
2420
+ });
2421
+ });
2422
+ }
2423
+ async function reservePortRange(size = PORT_RANGE_SIZE) {
2424
+ const held = [await reservePort()];
2425
+ const base = held[0].port;
2426
+ try {
2427
+ for (let i = 1; i < size; i++) {
2428
+ const candidate = base + i;
2429
+ const next = await tryReservePort(candidate);
2430
+ if (next) {
2431
+ held.push(next);
2432
+ } else {
2433
+ held.push(await reservePort());
2434
+ }
2414
2435
  }
2436
+ return held;
2437
+ } catch (err) {
2438
+ await Promise.all(held.map((h) => h.release()));
2439
+ throw err;
2415
2440
  }
2416
- return ports;
2417
2441
  }
2418
2442
  async function startDevServer(repoPath, worktreePath, onLine, opts) {
2419
2443
  const script = getRunScript(worktreePath, repoPath, opts?.scriptName);
2420
2444
  if (!script) return null;
2421
- const ports = await allocatePortRange(PORT_RANGE_SIZE);
2422
- const handle = await spawnWorkspaceScript(script.command, {
2423
- worktreePath,
2424
- repoPath,
2425
- ports,
2426
- defaultBranch: opts?.defaultBranch,
2427
- onLine
2428
- });
2429
- return {
2430
- pid: handle.pid,
2431
- port: ports[0],
2432
- ports,
2433
- scriptName: script.name,
2434
- kill: handle.kill,
2435
- done: handle.done
2436
- };
2445
+ const held = await reservePortRange(PORT_RANGE_SIZE);
2446
+ const ports = held.map((h) => h.port);
2447
+ try {
2448
+ await Promise.all(held.map((h) => h.release()));
2449
+ const handle = await spawnWorkspaceScript(script.command, {
2450
+ worktreePath,
2451
+ repoPath,
2452
+ ports,
2453
+ defaultBranch: opts?.defaultBranch,
2454
+ onLine
2455
+ });
2456
+ return {
2457
+ pid: handle.pid,
2458
+ port: ports[0],
2459
+ ports,
2460
+ scriptName: script.name,
2461
+ kill: handle.kill,
2462
+ done: handle.done
2463
+ };
2464
+ } catch (err) {
2465
+ await Promise.all(held.map((h) => h.release()));
2466
+ throw err;
2467
+ }
2437
2468
  }
2438
2469
 
2439
2470
  // src/store/setup-log.ts
@@ -3887,7 +3918,7 @@ async function createThread(input, _onSetupLine) {
3887
3918
  });
3888
3919
  await requireAgent(resolved.agent);
3889
3920
  if (input.cowboy) {
3890
- const { cowboyModeEnabled } = await import("./app-settings-5RQMQKSB.js");
3921
+ const { cowboyModeEnabled } = await import("./app-settings-KBL2G7M4.js");
3891
3922
  if (!cowboyModeEnabled()) {
3892
3923
  throw new Error(
3893
3924
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -3945,7 +3976,7 @@ async function createThread(input, _onSetupLine) {
3945
3976
  let sourceIsFork = false;
3946
3977
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
3947
3978
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
3948
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-BF253OZT.js");
3979
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-WZNDTRVL.js");
3949
3980
  const task = await ensureAbleTimeTask({
3950
3981
  title: title?.trim() || "Untitled work",
3951
3982
  description: input.prompt?.trim() || void 0
@@ -4508,7 +4539,7 @@ async function adoptThread(input) {
4508
4539
  messages: input.messages ?? []
4509
4540
  });
4510
4541
  writeThread(thread);
4511
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-TDBA64II.js");
4542
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-WXRPLT2N.js");
4512
4543
  await ensureWorkspace2(repoPath);
4513
4544
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-K7QK4RI5.js");
4514
4545
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -6566,12 +6597,13 @@ function formatLongRunningDirective(opts) {
6566
6597
  "- Loop Sideboard MCP `wait_for_job` (returns in ~45s). The desktop opens a `type=log` pane from wait/stop (and shell detached-job JSON) automatically \u2014 you may still `present_artifact` with `artifact_id=<id>` for a custom title. stillRunning \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
6567
6598
  "- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
6568
6599
  "- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
6569
- "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
6600
+ "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available).",
6601
+ "Project Dev / run scripts (`.sideboard` `[scripts.run.*]`, same as the desktop Dev button): use MCP `list_run_scripts` / `run_dev_script` / `stop_dev_script` \u2014 logs and Stop live in the thread UI. Do not detached-job or shell-spawn that same command."
6570
6602
  ].join("\n");
6571
6603
  }
6572
6604
  function formatLongRunningReminder(opts) {
6573
6605
  const invoke = formatDetachedJobInvoke(opts?.scriptPath);
6574
- return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn.`;
6606
+ return `Long jobs: \`${invoke} start <id> -- <cmd>\`, loop wait_for_job (or detached-job wait). The log pane updates from wait JSON; present_artifact type=log is optional. stop_job if hanging or wrong. Do not say you will let the user know later \u2014 stay in the turn. Project Dev button: list_run_scripts / run_dev_script / stop_dev_script (UI-connected \u2014 not detached-job).`;
6575
6607
  }
6576
6608
  function formatArtifactDirective() {
6577
6609
  return [
@@ -6583,7 +6615,7 @@ function formatArtifactDirective() {
6583
6615
  ].join("\n");
6584
6616
  }
6585
6617
  function formatUiReminder() {
6586
- return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
6618
+ return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button); stop_dev_script to stop.";
6587
6619
  }
6588
6620
 
6589
6621
  // src/review/review-write-gate.ts
@@ -6983,7 +7015,7 @@ function formatScheduledPrompt(name, prompt) {
6983
7015
  ${prompt}`;
6984
7016
  }
6985
7017
  async function defaultDeps() {
6986
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-CWOSAYAE.js");
7018
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-GKAHLGXT.js");
6987
7019
  const orch = getOrchestrator2();
6988
7020
  return {
6989
7021
  findThread: (id) => findThreadByRef(id),
@@ -7164,6 +7196,8 @@ var Orchestrator = class {
7164
7196
  /** Auto-continues after a worktree turn ended while a detached job still runs. */
7165
7197
  jobContinueCount = /* @__PURE__ */ new Map();
7166
7198
  jobContinueNudged = /* @__PURE__ */ new Set();
7199
+ /** In-flight startDev per worktree run key — agent MCP + UI Start must not double-spawn. */
7200
+ startingDev = /* @__PURE__ */ new Map();
7167
7201
  maxConcurrent;
7168
7202
  runningCount = 0;
7169
7203
  constructor(opts) {
@@ -7298,7 +7332,7 @@ var Orchestrator = class {
7298
7332
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
7299
7333
  });
7300
7334
  }
7301
- const { autoCleanupOrphansEnabled } = await import("./app-settings-5RQMQKSB.js");
7335
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-KBL2G7M4.js");
7302
7336
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
7303
7337
  await cleanupOrphanWorktrees({ repoPaths });
7304
7338
  }
@@ -7585,7 +7619,7 @@ var Orchestrator = class {
7585
7619
  }
7586
7620
  await setup;
7587
7621
  if (skipSetup) return;
7588
- const { autoRunAfterSetupEnabled } = await import("./app-settings-5RQMQKSB.js");
7622
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-KBL2G7M4.js");
7589
7623
  if (autoRunAfterSetupEnabled()) {
7590
7624
  try {
7591
7625
  await this.startDev(threadId);
@@ -7941,7 +7975,7 @@ var Orchestrator = class {
7941
7975
  }
7942
7976
  const isBrightsy = fresh.agent === "brightsy";
7943
7977
  const isOrchestration = isOrchestratorThread(fresh);
7944
- const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-5RQMQKSB.js");
7978
+ const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-KBL2G7M4.js");
7945
7979
  const gitAuthMode = getGithubGitAuthMode();
7946
7980
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
7947
7981
  githubSlug: await withTimeout(
@@ -8381,9 +8415,20 @@ var Orchestrator = class {
8381
8415
  "No run script found for this worktree. Add [scripts.run.*] in the worktree\u2019s .sideboard/settings.toml or .conductor/settings.toml (or settings.local.toml on the main repo)."
8382
8416
  );
8383
8417
  }
8418
+ const runKey = worktreeRunProcessKey(thread.worktreePath, resolvedName);
8419
+ const inFlight = this.startingDev.get(runKey);
8420
+ if (inFlight) return inFlight;
8421
+ const start = this.startDevUnlocked(thread, resolvedName, scriptName, scripts, runKey);
8422
+ this.startingDev.set(runKey, start);
8423
+ try {
8424
+ return await start;
8425
+ } finally {
8426
+ this.startingDev.delete(runKey);
8427
+ }
8428
+ }
8429
+ async startDevUnlocked(thread, resolvedName, scriptName, scripts, runKey) {
8384
8430
  const siblings = threadsSharingWorktree(thread.worktreePath);
8385
8431
  const shared = mergeWorktreeActiveRuns(siblings);
8386
- const runKey = worktreeRunProcessKey(thread.worktreePath, resolvedName);
8387
8432
  const existing = this.processes.get(runKey) ?? siblings.map((t) => this.processes.get(`${t.id}:run:${resolvedName}`)).find(Boolean);
8388
8433
  const active = shared.activeRuns.find((r) => r.scriptName === resolvedName);
8389
8434
  if (existing && active) {
@@ -8395,6 +8440,14 @@ var Orchestrator = class {
8395
8440
  return { port: shared.devPort, scriptName: resolvedName, ports: [shared.devPort] };
8396
8441
  }
8397
8442
  }
8443
+ if (active && !existing) {
8444
+ killListenersOnPorts(collectActiveRunPorts([active]));
8445
+ this.syncWorktreeRuns(
8446
+ thread.worktreePath,
8447
+ shared.activeRuns.filter((r) => r.scriptName !== resolvedName),
8448
+ shared.devPort === active.port ? null : shared.devPort
8449
+ );
8450
+ }
8398
8451
  const mode = getRunMode(thread.worktreePath, thread.repoPath);
8399
8452
  if (mode === "nonconcurrent") {
8400
8453
  const here = normalizeWorktreePath(thread.worktreePath);
@@ -8443,6 +8496,7 @@ var Orchestrator = class {
8443
8496
  kill: handle.kill
8444
8497
  });
8445
8498
  }
8499
+ const latestShared = mergeWorktreeActiveRuns(threadsSharingWorktree(thread.worktreePath));
8446
8500
  const run2 = {
8447
8501
  scriptName: resolvedName,
8448
8502
  port: handle.port,
@@ -8450,13 +8504,13 @@ var Orchestrator = class {
8450
8504
  startedAt
8451
8505
  };
8452
8506
  const nextRuns = [
8453
- ...shared.activeRuns.filter((r) => r.scriptName !== resolvedName),
8507
+ ...latestShared.activeRuns.filter((r) => r.scriptName !== resolvedName),
8454
8508
  run2
8455
8509
  ];
8456
8510
  this.syncWorktreeRuns(
8457
8511
  thread.worktreePath,
8458
8512
  nextRuns,
8459
- isDefault ? handle.port : shared.devPort
8513
+ isDefault ? handle.port : latestShared.devPort
8460
8514
  );
8461
8515
  this.emit({
8462
8516
  type: "dev_server_started",
@@ -9065,7 +9119,7 @@ var Orchestrator = class {
9065
9119
  if (!titled.userSetTitle && meta.title && titled.title !== meta.title) {
9066
9120
  updateThread(thread.id, { title: meta.title });
9067
9121
  }
9068
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-5RQMQKSB.js");
9122
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-KBL2G7M4.js");
9069
9123
  const latest = this.requireThread(thread.id);
9070
9124
  if (!shouldAutoArchiveOnPrMerge({
9071
9125
  previousPrState: prevState || null,
@@ -9347,7 +9401,7 @@ var Orchestrator = class {
9347
9401
  this.enforceHistoryRetention();
9348
9402
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
9349
9403
  try {
9350
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-TDBA64II.js");
9404
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-WXRPLT2N.js");
9351
9405
  await ensureWorkspace2(thread.repoPath);
9352
9406
  } catch {
9353
9407
  }
@@ -9374,7 +9428,7 @@ var Orchestrator = class {
9374
9428
  await runArchiveScript(thread.repoPath, thread.worktreePath);
9375
9429
  } catch {
9376
9430
  }
9377
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-5RQMQKSB.js");
9431
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-KBL2G7M4.js");
9378
9432
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
9379
9433
  await removeWorktree(thread.repoPath, thread.worktreePath, {
9380
9434
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -9401,7 +9455,7 @@ var Orchestrator = class {
9401
9455
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
9402
9456
  );
9403
9457
  }
9404
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-I573UOPD.js");
9458
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-L6FJXFUC.js");
9405
9459
  const slug = thread.worktreePath.split("/").pop();
9406
9460
  const dest = thread.worktreePath;
9407
9461
  await withRepoGitLock(thread.repoPath, async () => {
@@ -9511,7 +9565,7 @@ async function startOrchestration(opts) {
9511
9565
  sourceRef: "default",
9512
9566
  ...createOpts
9513
9567
  }).catch(async () => {
9514
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-I573UOPD.js");
9568
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-L6FJXFUC.js");
9515
9569
  const repo = await resolveRepoRoot2(repoPath);
9516
9570
  const def = await resolveDefaultBranch2(repo);
9517
9571
  return orch.createThread({
@@ -9541,6 +9595,7 @@ export {
9541
9595
  recordSlackOutboundWatch,
9542
9596
  pollSlackOutboundWatches,
9543
9597
  AGENT_GIT_ACTIONS,
9598
+ threadsSharingWorktree,
9544
9599
  mcpWaitForTurnTimeoutMs,
9545
9600
  mcpWaitStillRunningHint,
9546
9601
  mcpWaitFinishedHint,
@@ -6,7 +6,7 @@ import {
6
6
  resolveRepoRoot,
7
7
  takenSlugsFromThread,
8
8
  teamSlugFromName
9
- } from "./chunk-KTZESHYH.js";
9
+ } from "./chunk-AMMRFFB7.js";
10
10
  import {
11
11
  ATTACHMENTS_DIR,
12
12
  attachmentsGitignoreBody
@@ -23,7 +23,7 @@ import {
23
23
  resolveThreadDefaults,
24
24
  resolveViewerProfile,
25
25
  resolveViewerProfileForRepo
26
- } from "./chunk-EWHJNJHV.js";
26
+ } from "./chunk-I5NC7DWO.js";
27
27
  import {
28
28
  createEmptyThread,
29
29
  listThreads,