@sideboard-ai/core 0.1.152 → 0.1.155

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 (61) hide show
  1. package/dist/{abletime-223A3LY6.js → abletime-H7LPGIP2.js} +3 -3
  2. package/dist/{abletime-CLC5UJC2.js → abletime-JSTJLXAW.js} +3 -3
  3. package/dist/agents/cursor-runner.js +2 -2
  4. package/dist/{agents-CUKWIM34.js → agents-V24DYZI4.js} +8 -9
  5. package/dist/{agents-VHXCBBBD.js → agents-YVW75KBO.js} +8 -9
  6. package/dist/{app-settings-3CHCNIMD.js → app-settings-H3INSR67.js} +38 -4
  7. package/dist/{app-settings-J3JBCUOT.js → app-settings-VRQI3FIE.js} +38 -4
  8. package/dist/{caffeinate-hold-NBRUWYXO.js → caffeinate-hold-DBKMRZZO.js} +2 -2
  9. package/dist/{caffeinate-hold-X3JNPR42.js → caffeinate-hold-SK2QISPE.js} +2 -2
  10. package/dist/chunk-2F63IMCL.js +959 -0
  11. package/dist/{chunk-4XNSGDXE.js → chunk-3BWVOUQG.js} +244 -1
  12. package/dist/{chunk-7BQNSUR2.js → chunk-46ZTBUVJ.js} +364 -200
  13. package/dist/{chunk-EY6QXPPO.js → chunk-4THE3EY7.js} +6 -6
  14. package/dist/{chunk-TUGKX5BD.js → chunk-7UURXPKD.js} +1 -1
  15. package/dist/{chunk-DCOZABNT.js → chunk-AO35MGOE.js} +1 -1
  16. package/dist/{chunk-3JBMACYX.js → chunk-CJQLPPEJ.js} +387 -15
  17. package/dist/{chunk-CZD4NRDZ.js → chunk-D7EGJ3EI.js} +244 -1
  18. package/dist/{chunk-QZQEXME2.js → chunk-EFVFB2AH.js} +1 -1
  19. package/dist/{chunk-B7XK37WZ.js → chunk-FDCFXMDG.js} +1 -1
  20. package/dist/{chunk-6X7Z34XE.js → chunk-J2OKVOBM.js} +410 -188
  21. package/dist/{chunk-WLV7TRMR.js → chunk-JOK4XWBG.js} +1 -1
  22. package/dist/{chunk-BD2ICC4D.js → chunk-JTJHOYCU.js} +1 -1
  23. package/dist/{chunk-GE7M3QTE.js → chunk-LQMFCS54.js} +387 -15
  24. package/dist/{chunk-G7SIQFBQ.js → chunk-LZ6QMEQC.js} +1 -1
  25. package/dist/{chunk-EUXOHTUK.js → chunk-LZQULFIT.js} +1 -1
  26. package/dist/{chunk-KLBOWJ74.js → chunk-OCQPTUR7.js} +1 -1
  27. package/dist/{chunk-GFQ57XAX.js → chunk-QZEZXYVV.js} +13 -13
  28. package/dist/chunk-RNC3GR6L.js +905 -0
  29. package/dist/{chunk-VHX673DI.js → chunk-WLPXZFRE.js} +1 -1
  30. package/dist/{chunk-7F4XE6UG.js → chunk-XD2BAANL.js} +5 -5
  31. package/dist/{connected-teams-XO766HB4.js → connected-teams-DBWAMP7G.js} +2 -2
  32. package/dist/{connected-teams-I2WZZZFA.js → connected-teams-WGONUQOF.js} +2 -2
  33. package/dist/{coordinator-prompt-WGFRYCHE.js → coordinator-prompt-7FHKCWXB.js} +5 -5
  34. package/dist/{coordinator-prompt-TBX4MOFM.js → coordinator-prompt-KX2FVVYT.js} +5 -5
  35. package/dist/{cursor-recover-NOQYOFRF.js → cursor-recover-L5MD6MBO.js} +1 -1
  36. package/dist/{cursor-recover-QSLWEZNA.js → cursor-recover-NDMLLNYX.js} +2 -2
  37. package/dist/{global-workspace-IY5QAV5C.js → global-workspace-2BRRKSDN.js} +5 -6
  38. package/dist/{global-workspace-BHLUJ46D.js → global-workspace-4LHCZ2DC.js} +5 -6
  39. package/dist/index.cjs +1889 -777
  40. package/dist/index.d.cts +222 -12
  41. package/dist/index.d.ts +222 -12
  42. package/dist/index.js +304 -108
  43. package/dist/mcp/run-stdio.cjs +1747 -1240
  44. package/dist/mcp/run-stdio.js +232 -80
  45. package/dist/{orchestrator-256DFPSX.js → orchestrator-3FWEKDAQ.js} +9 -11
  46. package/dist/{orchestrator-NUA6SEV7.js → orchestrator-HC7XVGJB.js} +10 -12
  47. package/dist/{paths-UMEDHOS5.js → paths-53TLA7VQ.js} +1 -1
  48. package/dist/{paths-QCI3MTO5.js → paths-RRCLNSJB.js} +1 -1
  49. package/dist/{thread-store-WGASXXXR.js → thread-store-KBFBHT5G.js} +2 -2
  50. package/dist/{thread-store-57ZLHR3A.js → thread-store-MVQU6HPJ.js} +2 -2
  51. package/dist/{workspaces-4FSXVIZM.js → workspaces-5UNDTN4G.js} +5 -7
  52. package/dist/{workspaces-NECIQTAO.js → workspaces-MQYNZXUK.js} +5 -7
  53. package/dist/{worktree-HTUM35NT.js → worktree-PEWDAX5O.js} +4 -4
  54. package/dist/{worktree-DPIREDFR.js → worktree-T4SWFSTT.js} +4 -4
  55. package/package.json +1 -1
  56. package/dist/chunk-2U6QF3PT.js +0 -211
  57. package/dist/chunk-67TIJ7S5.js +0 -122
  58. package/dist/chunk-7TIUOYBK.js +0 -213
  59. package/dist/chunk-G4MTYUWS.js +0 -592
  60. package/dist/chunk-K2ANSHUO.js +0 -120
  61. package/dist/chunk-SN6CMKF6.js +0 -538
@@ -33,18 +33,27 @@ import {
33
33
  summarizeTurnStderr,
34
34
  toolDescription,
35
35
  turnFailChatText
36
- } from "./chunk-EY6QXPPO.js";
36
+ } from "./chunk-4THE3EY7.js";
37
37
  import {
38
- addWorkspace,
39
- ensureWorkspace,
40
- removeWorkspace,
41
- syncWorkspacesFromThreads
42
- } from "./chunk-67TIJ7S5.js";
38
+ extractPresentedPlan,
39
+ readPlanFile,
40
+ writePlanFile
41
+ } from "./chunk-2SDMENAL.js";
42
+ import {
43
+ releaseCaffeinateHoldForThread
44
+ } from "./chunk-OCQPTUR7.js";
43
45
  import {
46
+ SLACK_REPLY_FORMATTING,
47
+ addWorkspace,
44
48
  assertOrchestratorCapableAgent,
45
49
  attachmentsFromWorktreePaths,
46
50
  coerceOrchestratorAgent,
51
+ coordinatorSystemPrompt,
52
+ coordinatorTurnReminder,
47
53
  createGlobalChat,
54
+ enrichWorkspacesWithGithub,
55
+ ensureGlobalCoordinatorCwd,
56
+ ensureWorkspace,
48
57
  healOrchestrationSoccerTitles,
49
58
  isCloudCoordinatorThread,
50
59
  isGlobalRepoPath,
@@ -54,24 +63,11 @@ import {
54
63
  isSlackCoordinatorThread,
55
64
  orchestratorSessionPoisonedByBuiltins,
56
65
  persistPendingFileAttachments,
66
+ removeWorkspace,
57
67
  stageAbsolutePathsAsAttachments,
58
- stageBuffersAsAttachments
59
- } from "./chunk-SN6CMKF6.js";
60
- import {
61
- extractPresentedPlan,
62
- readPlanFile,
63
- writePlanFile
64
- } from "./chunk-2SDMENAL.js";
65
- import {
66
- releaseCaffeinateHoldForThread
67
- } from "./chunk-KLBOWJ74.js";
68
- import {
69
- SLACK_REPLY_FORMATTING,
70
- coordinatorSystemPrompt,
71
- coordinatorTurnReminder,
72
- enrichWorkspacesWithGithub,
73
- ensureGlobalCoordinatorCwd
74
- } from "./chunk-7TIUOYBK.js";
68
+ stageBuffersAsAttachments,
69
+ syncWorkspacesFromThreads
70
+ } from "./chunk-RNC3GR6L.js";
75
71
  import {
76
72
  addPrStackLayer,
77
73
  allocateTeamName,
@@ -119,7 +115,7 @@ import {
119
115
  withRepoGitLock,
120
116
  worktreeDisplayLabelForGroup,
121
117
  worktreeNameFromPath
122
- } from "./chunk-3JBMACYX.js";
118
+ } from "./chunk-CJQLPPEJ.js";
123
119
  import {
124
120
  ATTACHMENTS_DIR,
125
121
  LEGACY_ATTACHMENTS_DIR
@@ -135,7 +131,7 @@ import {
135
131
  updateThread,
136
132
  withThreadLock,
137
133
  writeThread
138
- } from "./chunk-EUXOHTUK.js";
134
+ } from "./chunk-LZQULFIT.js";
139
135
  import {
140
136
  ensureWorktreeSideboardIgnored
141
137
  } from "./chunk-SYFVUF2C.js";
@@ -162,7 +158,7 @@ import {
162
158
  stripNestedElectronEnv,
163
159
  updateAdvancedSettings,
164
160
  writeSecureJson
165
- } from "./chunk-CZD4NRDZ.js";
161
+ } from "./chunk-D7EGJ3EI.js";
166
162
  import {
167
163
  writePrivateFile
168
164
  } from "./chunk-NSTQ6QKD.js";
@@ -175,9 +171,10 @@ import {
175
171
  sideboardReposDir,
176
172
  sideboardWorkspacesDir,
177
173
  threadLivePath,
174
+ threadsDir,
178
175
  workspaceSettingsSourceLabel,
179
176
  worktreesRoot
180
- } from "./chunk-BD2ICC4D.js";
177
+ } from "./chunk-JTJHOYCU.js";
181
178
 
182
179
  // src/orchestrator/orchestrator.ts
183
180
  import { EventEmitter } from "events";
@@ -395,7 +392,7 @@ async function continueSourceThread(threadId, prompt) {
395
392
  await continueOnReply(threadId, prompt);
396
393
  return;
397
394
  }
398
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-256DFPSX.js");
395
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-3FWEKDAQ.js");
399
396
  await getOrchestrator2().send(threadId, prompt);
400
397
  } catch {
401
398
  }
@@ -655,7 +652,7 @@ async function pollSlackOutboundWatches(opts) {
655
652
  }
656
653
 
657
654
  // src/orchestrator/orchestrator.ts
658
- import { existsSync as existsSync16 } from "fs";
655
+ import { existsSync as existsSync17 } from "fs";
659
656
 
660
657
  // src/agents/spawn.ts
661
658
  import { createInterface } from "readline";
@@ -736,9 +733,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
736
733
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
737
734
  );
738
735
  }
739
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-BHLUJ46D.js");
736
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-4LHCZ2DC.js");
740
737
  if (isGlobalThread2(thread)) {
741
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-TBX4MOFM.js");
738
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-KX2FVVYT.js");
742
739
  ensureGlobalCoordinatorCwd2(
743
740
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
744
741
  );
@@ -1940,6 +1937,8 @@ async function attachAbort(handle, signal) {
1940
1937
  async function runSetupScript(repoPath, worktreePath, onLine, opts) {
1941
1938
  const settings = loadWorkspaceSettings(worktreePath, repoPath);
1942
1939
  if (!settings?.setup) return { ran: false, exitCode: null, source: null };
1940
+ const source = workspaceSettingsSourceLabel(worktreePath, repoPath);
1941
+ onLine?.(`[setup] ${source ?? "settings.toml"}`);
1943
1942
  const handle = await spawnWorkspaceScript(settings.setup, {
1944
1943
  worktreePath,
1945
1944
  repoPath,
@@ -1950,7 +1949,7 @@ async function runSetupScript(repoPath, worktreePath, onLine, opts) {
1950
1949
  return {
1951
1950
  ran: true,
1952
1951
  exitCode,
1953
- source: workspaceSettingsSourceLabel(worktreePath, repoPath),
1952
+ source,
1954
1953
  kill: handle.kill
1955
1954
  };
1956
1955
  }
@@ -2079,9 +2078,114 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
2079
2078
  };
2080
2079
  }
2081
2080
 
2082
- // src/git/orphan-cleanup.ts
2083
- import { existsSync as existsSync5, readdirSync as readdirSync2, statSync } from "fs";
2081
+ // src/store/setup-log.ts
2082
+ import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
2084
2083
  import { join as join6 } from "path";
2084
+ var EMPTY = {
2085
+ output: "",
2086
+ running: false,
2087
+ exitCode: null,
2088
+ source: null
2089
+ };
2090
+ var memory = /* @__PURE__ */ new Map();
2091
+ var persistTimers = /* @__PURE__ */ new Map();
2092
+ function setupLogPath(threadId) {
2093
+ return join6(threadsDir(), `${threadId}.setup.log.json`);
2094
+ }
2095
+ function emptySetupLog() {
2096
+ return { ...EMPTY };
2097
+ }
2098
+ function clone(snap) {
2099
+ return { ...snap };
2100
+ }
2101
+ function persistNow(threadId) {
2102
+ const timer = persistTimers.get(threadId);
2103
+ if (timer) {
2104
+ clearTimeout(timer);
2105
+ persistTimers.delete(threadId);
2106
+ }
2107
+ const snap = memory.get(threadId);
2108
+ if (!snap) return;
2109
+ try {
2110
+ writeFileSync2(setupLogPath(threadId), `${JSON.stringify(snap)}
2111
+ `, "utf8");
2112
+ } catch {
2113
+ }
2114
+ }
2115
+ function schedulePersist(threadId) {
2116
+ if (persistTimers.has(threadId)) return;
2117
+ persistTimers.set(
2118
+ threadId,
2119
+ setTimeout(() => {
2120
+ persistTimers.delete(threadId);
2121
+ persistNow(threadId);
2122
+ }, 100)
2123
+ );
2124
+ }
2125
+ function loadFromDisk(threadId) {
2126
+ const path = setupLogPath(threadId);
2127
+ if (!existsSync5(path)) return null;
2128
+ try {
2129
+ const raw = JSON.parse(readFileSync5(path, "utf8"));
2130
+ return {
2131
+ output: typeof raw.output === "string" ? raw.output : "",
2132
+ running: Boolean(raw.running),
2133
+ exitCode: typeof raw.exitCode === "number" ? raw.exitCode : null,
2134
+ source: typeof raw.source === "string" ? raw.source : null
2135
+ };
2136
+ } catch {
2137
+ return null;
2138
+ }
2139
+ }
2140
+ function readSetupLog(threadId) {
2141
+ const cached = memory.get(threadId);
2142
+ if (cached) return clone(cached);
2143
+ const disk = loadFromDisk(threadId);
2144
+ if (disk) {
2145
+ memory.set(threadId, disk);
2146
+ return clone(disk);
2147
+ }
2148
+ return emptySetupLog();
2149
+ }
2150
+ function beginSetupLog(threadId) {
2151
+ const snap = {
2152
+ output: "",
2153
+ running: true,
2154
+ exitCode: null,
2155
+ source: null
2156
+ };
2157
+ memory.set(threadId, snap);
2158
+ persistNow(threadId);
2159
+ return clone(snap);
2160
+ }
2161
+ function appendSetupLog(threadId, line) {
2162
+ const current = memory.get(threadId) ?? readSetupLog(threadId);
2163
+ const snap = {
2164
+ ...current,
2165
+ output: current.output ? `${current.output}
2166
+ ${line}` : line,
2167
+ running: true
2168
+ };
2169
+ memory.set(threadId, snap);
2170
+ schedulePersist(threadId);
2171
+ return clone(snap);
2172
+ }
2173
+ function finishSetupLog(threadId, exitCode, source) {
2174
+ const current = memory.get(threadId) ?? readSetupLog(threadId);
2175
+ const snap = {
2176
+ ...current,
2177
+ running: false,
2178
+ exitCode,
2179
+ source: source ?? current.source
2180
+ };
2181
+ memory.set(threadId, snap);
2182
+ persistNow(threadId);
2183
+ return clone(snap);
2184
+ }
2185
+
2186
+ // src/git/orphan-cleanup.ts
2187
+ import { existsSync as existsSync6, readdirSync as readdirSync2, statSync } from "fs";
2188
+ import { join as join7 } from "path";
2085
2189
  function isSideboardWorktreePath(path) {
2086
2190
  return path.includes("/.sideboard/worktrees/") || path.includes("/sideboard/workspaces/");
2087
2191
  }
@@ -2092,7 +2196,7 @@ async function findOrphanWorktrees(repoPaths) {
2092
2196
  repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
2093
2197
  );
2094
2198
  const homeRoot = sideboardWorkspacesDir();
2095
- if (existsSync5(homeRoot)) {
2199
+ if (existsSync6(homeRoot)) {
2096
2200
  try {
2097
2201
  for (const entry of readdirSync2(homeRoot, { withFileTypes: true })) {
2098
2202
  if (!entry.isDirectory()) continue;
@@ -2104,7 +2208,7 @@ async function findOrphanWorktrees(repoPaths) {
2104
2208
  const orphans = [];
2105
2209
  const seen = /* @__PURE__ */ new Set();
2106
2210
  for (const repoPath of repos) {
2107
- if (!repoPath || !existsSync5(repoPath)) continue;
2211
+ if (!repoPath || !existsSync6(repoPath)) continue;
2108
2212
  try {
2109
2213
  const wts = await listWorktrees(repoPath);
2110
2214
  for (const wt of wts) {
@@ -2125,12 +2229,12 @@ async function findOrphanWorktrees(repoPaths) {
2125
2229
  }
2126
2230
  try {
2127
2231
  const root = worktreesRoot(repoPath);
2128
- if (existsSync5(root)) {
2232
+ if (existsSync6(root)) {
2129
2233
  for (const entry of readdirSync2(root, { withFileTypes: true })) {
2130
2234
  if (!entry.isDirectory()) continue;
2131
- const path = join6(root, entry.name).replace(/\/$/, "");
2235
+ const path = join7(root, entry.name).replace(/\/$/, "");
2132
2236
  if (known.has(path) || seen.has(path)) continue;
2133
- if (!existsSync5(join6(path, ".git"))) continue;
2237
+ if (!existsSync6(join7(path, ".git"))) continue;
2134
2238
  seen.add(path);
2135
2239
  let mtimeMs = 0;
2136
2240
  try {
@@ -2270,8 +2374,8 @@ async function applyThreadIntoMain(thread, opts) {
2270
2374
  }
2271
2375
 
2272
2376
  // src/git/clone-repo.ts
2273
- import { existsSync as existsSync6 } from "fs";
2274
- import { basename as basename2, join as join7 } from "path";
2377
+ import { existsSync as existsSync7 } from "fs";
2378
+ import { basename as basename2, join as join8 } from "path";
2275
2379
  import { execa as execa4 } from "execa";
2276
2380
  async function cloneRepoIntoSideboard(opts) {
2277
2381
  const url = opts.url.trim();
@@ -2282,8 +2386,8 @@ async function cloneRepoIntoSideboard(opts) {
2282
2386
  name = leaf || "repo";
2283
2387
  }
2284
2388
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
2285
- const dest = join7(sideboardReposDir(), name);
2286
- if (existsSync6(dest)) {
2389
+ const dest = join8(sideboardReposDir(), name);
2390
+ if (existsSync7(dest)) {
2287
2391
  const repoPath2 = await resolveRepoRoot(dest);
2288
2392
  const workspace2 = await ensureWorkspace(repoPath2);
2289
2393
  return { repoPath: repoPath2, workspace: workspace2 };
@@ -2300,14 +2404,14 @@ async function cloneRepoIntoSideboard(opts) {
2300
2404
  }
2301
2405
 
2302
2406
  // src/store/desktop-host.ts
2303
- import { readFileSync as readFileSync5, unlinkSync, writeFileSync as writeFileSync2 } from "fs";
2304
- import { join as join8 } from "path";
2407
+ import { readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
2408
+ import { join as join9 } from "path";
2305
2409
  function desktopHostPidPath() {
2306
- return join8(appDataDir(), "desktop-host.pid");
2410
+ return join9(appDataDir(), "desktop-host.pid");
2307
2411
  }
2308
2412
  function readDesktopHostPid() {
2309
2413
  try {
2310
- const pid = Number.parseInt(readFileSync5(desktopHostPidPath(), "utf8").trim(), 10);
2414
+ const pid = Number.parseInt(readFileSync6(desktopHostPidPath(), "utf8").trim(), 10);
2311
2415
  if (!Number.isFinite(pid) || pid <= 0) return null;
2312
2416
  return pid;
2313
2417
  } catch {
@@ -2374,7 +2478,7 @@ function notifyParentOfChildHalt(child, status, send) {
2374
2478
  }
2375
2479
 
2376
2480
  // src/threads/create.ts
2377
- import { existsSync as existsSync7 } from "fs";
2481
+ import { existsSync as existsSync8 } from "fs";
2378
2482
 
2379
2483
  // src/detect/detect.ts
2380
2484
  var REQUIRE_AGENT_TIMEOUT_MS = 8e3;
@@ -2540,12 +2644,19 @@ function urlsMatch(a, b) {
2540
2644
  const norm = (u) => u.trim().replace(/\/+$/, "").toLowerCase();
2541
2645
  return Boolean(a && b && norm(a) === norm(b));
2542
2646
  }
2647
+ function threadPrUrlMatchesNumber(thread, number) {
2648
+ if (!Number.isFinite(number) || number < 1) return false;
2649
+ const url = (thread.prUrl ?? "").trim();
2650
+ if (!url) return false;
2651
+ return new RegExp(`/pull/${number}(?:/|$|[?#])`, "i").test(url);
2652
+ }
2543
2653
  function threadMatchesPr(thread, pr) {
2544
2654
  const num = String(pr.number);
2545
2655
  if (thread.sourceType === "pr" && normalizeIssueKey(thread.sourceRef ?? "") === num) {
2546
2656
  return true;
2547
2657
  }
2548
2658
  if (thread.prUrl && pr.url && urlsMatch(thread.prUrl, pr.url)) return true;
2659
+ if (threadPrUrlMatchesNumber(thread, pr.number)) return true;
2549
2660
  const head = pr.headRefName.trim().toLowerCase();
2550
2661
  if (!head) return false;
2551
2662
  const branch = (thread.branchName ?? "").trim().toLowerCase();
@@ -2598,19 +2709,32 @@ function findLiveThreadForCreate(input, threads) {
2598
2709
  (t) => threadMatchesPr(t, {
2599
2710
  number: Number.isFinite(number) ? number : -1,
2600
2711
  title: input.title ?? "",
2601
- url: "",
2602
- headRefName: ""
2712
+ url: input.prUrl ?? "",
2713
+ headRefName: input.headRefName ?? ""
2603
2714
  })
2604
2715
  );
2605
2716
  }
2606
2717
  if (input.sourceType === "branch") {
2607
2718
  if (isDefaultBranchCreateRef(input.sourceRef)) return void 0;
2608
- return live.find(
2719
+ const byBranch = live.find(
2609
2720
  (t) => threadMatchesBranch(t, {
2610
2721
  ref: input.sourceRef,
2611
2722
  repoPath: input.repoPath
2612
2723
  })
2613
2724
  );
2725
+ if (byBranch) return byBranch;
2726
+ if (input.prUrl || input.headRefName) {
2727
+ const number = Number(normalizeIssueKey(input.sourceRef));
2728
+ return live.find(
2729
+ (t) => threadMatchesPr(t, {
2730
+ number: Number.isFinite(number) ? number : -1,
2731
+ title: input.title ?? "",
2732
+ url: input.prUrl ?? "",
2733
+ headRefName: input.headRefName ?? input.sourceRef
2734
+ })
2735
+ );
2736
+ }
2737
+ return void 0;
2614
2738
  }
2615
2739
  return void 0;
2616
2740
  }
@@ -2836,42 +2960,53 @@ function assembleHomeBoard(input) {
2836
2960
  }
2837
2961
  return { columns, hidden, totals };
2838
2962
  }
2839
- var HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards). create_thread reuses a live worktree for the same ticket, PR, or named branch \u2014 do not recreate it. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats stay in the sidebar. Do not invent status.";
2963
+ var HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards). Do not create a second worktree for a ticket, PR, or named branch that already has a live checkout \u2014 create_thread / start_board_card return that thread (alreadyStarted). Creating from the default branch still opens a new isolated worktree. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats stay in the sidebar. Do not invent status.";
2840
2964
 
2841
2965
  // src/threads/create.ts
2842
2966
  function persistCreateAttachments(worktreePath, attachments) {
2843
2967
  return persistPendingFileAttachments(worktreePath, attachments ?? []);
2844
2968
  }
2969
+ function liveThreadsForCreate() {
2970
+ return listThreads({ includeArchived: false }).map((t) => ({
2971
+ ...t,
2972
+ repoPath: canonicalizeRepoPath(t.repoPath)
2973
+ }));
2974
+ }
2975
+ function reuseLiveThread(input, repoPath, match) {
2976
+ if (input.reuseExisting === false) return void 0;
2977
+ const existing = findLiveThreadForCreate(
2978
+ {
2979
+ sourceType: match.sourceType,
2980
+ sourceRef: match.sourceRef,
2981
+ repoPath,
2982
+ title: match.title ?? input.title,
2983
+ cowboy: input.cowboy,
2984
+ prUrl: match.prUrl,
2985
+ headRefName: match.headRefName
2986
+ },
2987
+ liveThreadsForCreate()
2988
+ );
2989
+ if (!existing) return void 0;
2990
+ const thread = readThread(existing.id) ?? existing;
2991
+ if (!input.attachments?.length) return thread;
2992
+ return updateThread(thread.id, {
2993
+ attachments: persistCreateAttachments(thread.worktreePath, [
2994
+ ...thread.attachments,
2995
+ ...input.attachments
2996
+ ])
2997
+ });
2998
+ }
2845
2999
  async function createThread(input, _onSetupLine) {
2846
3000
  const repoPath = await resolveRepoRoot(input.repoPath);
2847
- if (!existsSync7(repoPath)) {
3001
+ if (!existsSync8(repoPath)) {
2848
3002
  throw new Error(`Repo not found: ${repoPath}`);
2849
3003
  }
2850
- if (input.reuseExisting !== false) {
2851
- const existing = findLiveThreadForCreate(
2852
- {
2853
- sourceType: input.sourceType,
2854
- sourceRef: input.sourceRef,
2855
- repoPath,
2856
- title: input.title,
2857
- cowboy: input.cowboy
2858
- },
2859
- listThreads({ includeArchived: false }).map((t) => ({
2860
- ...t,
2861
- repoPath: canonicalizeRepoPath(t.repoPath)
2862
- }))
2863
- );
2864
- if (existing) {
2865
- const thread2 = readThread(existing.id) ?? existing;
2866
- if (!input.attachments?.length) return thread2;
2867
- return updateThread(thread2.id, {
2868
- attachments: persistCreateAttachments(thread2.worktreePath, [
2869
- ...thread2.attachments,
2870
- ...input.attachments
2871
- ])
2872
- });
2873
- }
2874
- }
3004
+ const reused = reuseLiveThread(input, repoPath, {
3005
+ sourceType: input.sourceType,
3006
+ sourceRef: input.sourceRef,
3007
+ title: input.title
3008
+ });
3009
+ if (reused) return reused;
2875
3010
  const resolved = resolveNewThreadOptions({
2876
3011
  agent: input.agent,
2877
3012
  model: input.model,
@@ -2880,7 +3015,7 @@ async function createThread(input, _onSetupLine) {
2880
3015
  });
2881
3016
  await requireAgent(resolved.agent);
2882
3017
  if (input.cowboy) {
2883
- const { cowboyModeEnabled } = await import("./app-settings-J3JBCUOT.js");
3018
+ const { cowboyModeEnabled } = await import("./app-settings-VRQI3FIE.js");
2884
3019
  if (!cowboyModeEnabled()) {
2885
3020
  throw new Error(
2886
3021
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -2938,7 +3073,7 @@ async function createThread(input, _onSetupLine) {
2938
3073
  let sourceIsFork = false;
2939
3074
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
2940
3075
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
2941
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-CLC5UJC2.js");
3076
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-JSTJLXAW.js");
2942
3077
  const task = await ensureAbleTimeTask({
2943
3078
  title: title?.trim() || "Untitled work",
2944
3079
  description: input.prompt?.trim() || void 0
@@ -2948,6 +3083,12 @@ async function createThread(input, _onSetupLine) {
2948
3083
  persistedSourceRef = task.identifier;
2949
3084
  title = title?.trim() || task.title;
2950
3085
  attachments = [...attachments, issueAttachmentForAbleTimeTask(task)];
3086
+ const reusedTicket = reuseLiveThread(
3087
+ { ...input, sourceType: "ticket", sourceRef, title, attachments },
3088
+ repoPath,
3089
+ { sourceType: "ticket", sourceRef, title }
3090
+ );
3091
+ if (reusedTicket) return reusedTicket;
2951
3092
  }
2952
3093
  }
2953
3094
  let prUrl = null;
@@ -2957,6 +3098,14 @@ async function createThread(input, _onSetupLine) {
2957
3098
  if (!Number.isFinite(num)) throw new Error(`Invalid PR number: ${input.sourceRef}`);
2958
3099
  const pr = await getPr(repoPath, num);
2959
3100
  if (!pr) throw new Error(`PR #${num} not found`);
3101
+ const reusedPr = reuseLiveThread(input, repoPath, {
3102
+ sourceType: "pr",
3103
+ sourceRef: String(pr.number),
3104
+ title: input.title ?? pr.title,
3105
+ prUrl: pr.url,
3106
+ headRefName: pr.headRefName
3107
+ });
3108
+ if (reusedPr) return reusedPr;
2960
3109
  sourceIsFork = pr.isCrossRepository;
2961
3110
  prUrl = pr.url;
2962
3111
  const localFetchBranch = `sideboard-pr-${pr.number}`;
@@ -2969,9 +3118,19 @@ async function createThread(input, _onSetupLine) {
2969
3118
  sourceRef = await resolveDefaultBranch(repoPath);
2970
3119
  } else {
2971
3120
  const existing = await getPrForHeadBranch(repoPath, sourceRef);
2972
- if (existing?.url) {
2973
- prUrl = existing.url;
2974
- prTitle = existing.title;
3121
+ if (existing) {
3122
+ const reusedPr = reuseLiveThread(input, repoPath, {
3123
+ sourceType: "pr",
3124
+ sourceRef: String(existing.number),
3125
+ title: input.title ?? existing.title,
3126
+ prUrl: existing.url,
3127
+ headRefName: existing.headRefName
3128
+ });
3129
+ if (reusedPr) return reusedPr;
3130
+ if (existing.url) {
3131
+ prUrl = existing.url;
3132
+ prTitle = existing.title;
3133
+ }
2975
3134
  }
2976
3135
  }
2977
3136
  } else if (sourceType === "adopt") {
@@ -3010,15 +3169,6 @@ async function createThread(input, _onSetupLine) {
3010
3169
  await ensureWorkspace(repoPath);
3011
3170
  return readThread(thread.id) ?? thread;
3012
3171
  }
3013
- async function listLinearIssues(agent, repoPath) {
3014
- const { getAdapter: getAdapter2 } = await import("./agents-CUKWIM34.js");
3015
- await requireAgent(agent, { requireLinear: true });
3016
- const adapter = getAdapter2(agent);
3017
- if (!adapter.listLinearIssues) {
3018
- throw new Error(`${agent} does not support Linear issue listing`);
3019
- }
3020
- return adapter.listLinearIssues(repoPath);
3021
- }
3022
3172
 
3023
3173
  // src/threads/cowboy.ts
3024
3174
  function isCowboyThread(thread) {
@@ -3034,11 +3184,11 @@ function shouldRemoveWorktreeOnTeardown(thread) {
3034
3184
 
3035
3185
  // src/store/turn-live.ts
3036
3186
  import {
3037
- existsSync as existsSync8,
3187
+ existsSync as existsSync9,
3038
3188
  renameSync,
3039
3189
  unlinkSync as unlinkSync2,
3040
- writeFileSync as writeFileSync3,
3041
- readFileSync as readFileSync6
3190
+ writeFileSync as writeFileSync4,
3191
+ readFileSync as readFileSync7
3042
3192
  } from "fs";
3043
3193
  var buffers = /* @__PURE__ */ new Map();
3044
3194
  var FLUSH_MS = 800;
@@ -3115,7 +3265,7 @@ function writeTurnLive(threadId, progress) {
3115
3265
  const path = threadLivePath(threadId);
3116
3266
  const tmp = `${path}.${process.pid}.tmp`;
3117
3267
  try {
3118
- writeFileSync3(tmp, JSON.stringify(progress), "utf8");
3268
+ writeFileSync4(tmp, JSON.stringify(progress), "utf8");
3119
3269
  renameSync(tmp, path);
3120
3270
  } catch {
3121
3271
  try {
@@ -3126,9 +3276,9 @@ function writeTurnLive(threadId, progress) {
3126
3276
  }
3127
3277
  function readTurnLive(threadId) {
3128
3278
  const path = threadLivePath(threadId);
3129
- if (!existsSync8(path)) return null;
3279
+ if (!existsSync9(path)) return null;
3130
3280
  try {
3131
- const raw = JSON.parse(readFileSync6(path, "utf8"));
3281
+ const raw = JSON.parse(readFileSync7(path, "utf8"));
3132
3282
  if (!raw || typeof raw.summary !== "string") return null;
3133
3283
  return raw;
3134
3284
  } catch {
@@ -3140,7 +3290,7 @@ function clearTurnLive(threadId) {
3140
3290
  if (buf?.timer) clearTimeout(buf.timer);
3141
3291
  buffers.delete(threadId);
3142
3292
  const path = threadLivePath(threadId);
3143
- if (!existsSync8(path)) return;
3293
+ if (!existsSync9(path)) return;
3144
3294
  try {
3145
3295
  unlinkSync2(path);
3146
3296
  } catch {
@@ -3165,7 +3315,8 @@ function shouldReadThreadToHealReconcile(eventType, lastCheckAt, now) {
3165
3315
  // src/orchestrator/setup-last-error.ts
3166
3316
  function shouldStampSetupLastError(opts) {
3167
3317
  if (opts.turnInFlight) return false;
3168
- if (opts.status === "running") return false;
3318
+ if (opts.status === "running" || opts.status === "queued") return false;
3319
+ if (opts.hasQueuedPrompt) return false;
3169
3320
  return true;
3170
3321
  }
3171
3322
  function isStaleLastErrorDuringTurn(err) {
@@ -3324,26 +3475,26 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
3324
3475
  import { execFileSync } from "child_process";
3325
3476
  import {
3326
3477
  copyFileSync as copyFileSync2,
3327
- existsSync as existsSync9,
3478
+ existsSync as existsSync10,
3328
3479
  mkdtempSync,
3329
3480
  readdirSync as readdirSync3,
3330
- readFileSync as readFileSync7,
3481
+ readFileSync as readFileSync8,
3331
3482
  rmSync
3332
3483
  } from "fs";
3333
3484
  import { tmpdir } from "os";
3334
- import { join as join9 } from "path";
3485
+ import { join as join10 } from "path";
3335
3486
  import { createRequire } from "module";
3336
- var CONDUCTOR_APP_SUPPORT = join9(
3487
+ var CONDUCTOR_APP_SUPPORT = join10(
3337
3488
  process.env.HOME ?? "",
3338
3489
  "Library",
3339
3490
  "Application Support",
3340
3491
  "com.conductor.app"
3341
3492
  );
3342
- var CONDUCTOR_DB = join9(CONDUCTOR_APP_SUPPORT, "conductor.db");
3343
- var CURSOR_SDK_STORE = join9(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
3493
+ var CONDUCTOR_DB = join10(CONDUCTOR_APP_SUPPORT, "conductor.db");
3494
+ var CURSOR_SDK_STORE = join10(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
3344
3495
  function thisModuleFile() {
3345
3496
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
3346
- return cjsFile || process.argv[1] || join9(process.cwd(), "package.json");
3497
+ return cjsFile || process.argv[1] || join10(process.cwd(), "package.json");
3347
3498
  }
3348
3499
  function openReadonlySqlite(file) {
3349
3500
  const req = createRequire(thisModuleFile());
@@ -3361,7 +3512,7 @@ function mapAgentType(raw) {
3361
3512
  return null;
3362
3513
  }
3363
3514
  function resolveConductorCursorAgentId(workspacePath) {
3364
- if (!workspacePath || !existsSync9(CURSOR_SDK_STORE)) return null;
3515
+ if (!workspacePath || !existsSync10(CURSOR_SDK_STORE)) return null;
3365
3516
  const normalized = workspacePath.replace(/\/$/, "");
3366
3517
  let best = null;
3367
3518
  let hashes;
@@ -3371,11 +3522,11 @@ function resolveConductorCursorAgentId(workspacePath) {
3371
3522
  return null;
3372
3523
  }
3373
3524
  for (const hash of hashes) {
3374
- const agentsFile = join9(CURSOR_SDK_STORE, hash, "agents.ndjson");
3375
- if (!existsSync9(agentsFile)) continue;
3525
+ const agentsFile = join10(CURSOR_SDK_STORE, hash, "agents.ndjson");
3526
+ if (!existsSync10(agentsFile)) continue;
3376
3527
  let text;
3377
3528
  try {
3378
- text = readFileSync7(agentsFile, "utf8");
3529
+ text = readFileSync8(agentsFile, "utf8");
3379
3530
  } catch {
3380
3531
  continue;
3381
3532
  }
@@ -3399,7 +3550,7 @@ function resolveConductorCursorAgentId(workspacePath) {
3399
3550
  return best?.agentId ?? null;
3400
3551
  }
3401
3552
  async function adoptThread(input) {
3402
- if (!existsSync9(input.worktreePath)) {
3553
+ if (!existsSync10(input.worktreePath)) {
3403
3554
  throw new Error(`Worktree not found: ${input.worktreePath}`);
3404
3555
  }
3405
3556
  const repoPath = await resolveRepoRoot(input.worktreePath);
@@ -3418,23 +3569,23 @@ async function adoptThread(input) {
3418
3569
  messages: input.messages ?? []
3419
3570
  });
3420
3571
  writeThread(thread);
3421
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-NECIQTAO.js");
3572
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-MQYNZXUK.js");
3422
3573
  await ensureWorkspace2(repoPath);
3423
3574
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-N5X5I422.js");
3424
3575
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
3425
3576
  return thread;
3426
3577
  }
3427
3578
  function listConductorWorkspaces() {
3428
- if (!existsSync9(CONDUCTOR_DB)) {
3579
+ if (!existsSync10(CONDUCTOR_DB)) {
3429
3580
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
3430
3581
  }
3431
- const tmp = mkdtempSync(join9(tmpdir(), "sideboard-conductor-"));
3432
- const snapshot = join9(tmp, "conductor.db");
3582
+ const tmp = mkdtempSync(join10(tmpdir(), "sideboard-conductor-"));
3583
+ const snapshot = join10(tmp, "conductor.db");
3433
3584
  try {
3434
3585
  copyFileSync2(CONDUCTOR_DB, snapshot);
3435
3586
  for (const suffix of ["-wal", "-shm"]) {
3436
3587
  const src = `${CONDUCTOR_DB}${suffix}`;
3437
- if (existsSync9(src)) {
3588
+ if (existsSync10(src)) {
3438
3589
  try {
3439
3590
  copyFileSync2(src, `${snapshot}${suffix}`);
3440
3591
  } catch {
@@ -3516,16 +3667,16 @@ function listConductorWorkspaces() {
3516
3667
  }
3517
3668
  }
3518
3669
  function importConductorWorkspace(workspaceId) {
3519
- if (!existsSync9(CONDUCTOR_DB)) {
3670
+ if (!existsSync10(CONDUCTOR_DB)) {
3520
3671
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
3521
3672
  }
3522
- const tmp = mkdtempSync(join9(tmpdir(), "sideboard-conductor-"));
3523
- const snapshot = join9(tmp, "conductor.db");
3673
+ const tmp = mkdtempSync(join10(tmpdir(), "sideboard-conductor-"));
3674
+ const snapshot = join10(tmp, "conductor.db");
3524
3675
  try {
3525
3676
  copyFileSync2(CONDUCTOR_DB, snapshot);
3526
3677
  for (const suffix of ["-wal", "-shm"]) {
3527
3678
  const src = `${CONDUCTOR_DB}${suffix}`;
3528
- if (existsSync9(src)) {
3679
+ if (existsSync10(src)) {
3529
3680
  try {
3530
3681
  copyFileSync2(src, `${snapshot}${suffix}`);
3531
3682
  } catch {
@@ -3545,7 +3696,7 @@ function importConductorWorkspace(workspaceId) {
3545
3696
  ).get(workspaceId);
3546
3697
  if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
3547
3698
  const worktreePath = String(row.workspacePath);
3548
- if (!existsSync9(worktreePath)) {
3699
+ if (!existsSync10(worktreePath)) {
3549
3700
  throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
3550
3701
  }
3551
3702
  let sessionId = null;
@@ -3616,7 +3767,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
3616
3767
  }
3617
3768
 
3618
3769
  // src/threads/stack-layers.ts
3619
- import { existsSync as existsSync10 } from "fs";
3770
+ import { existsSync as existsSync11 } from "fs";
3620
3771
  function stackIdFrom(stack) {
3621
3772
  if (stack.stackNumber != null) return `gh-stack-${stack.stackNumber}`;
3622
3773
  const key = stack.layers.map((l) => l.branchName).join("|");
@@ -3679,7 +3830,7 @@ async function openStackLayer(input, _onSetupLine) {
3679
3830
  let createdWorktree = false;
3680
3831
  const trees = await listWorktrees(repoPath);
3681
3832
  const checkedOut = trees.find((w) => w.branch === branchName);
3682
- if (checkedOut?.path && existsSync10(checkedOut.path)) {
3833
+ if (checkedOut?.path && existsSync11(checkedOut.path)) {
3683
3834
  if (input.reuseExistingWorktree !== false) {
3684
3835
  worktreePath = checkedOut.path;
3685
3836
  } else {
@@ -3821,7 +3972,7 @@ async function initStackFromThread(input, onSetupLine) {
3821
3972
  async function createPrStack(input, onSetupLine) {
3822
3973
  await requireAgent(input.agent);
3823
3974
  const repoPath = await resolveRepoRoot(input.repoPath);
3824
- if (!existsSync10(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
3975
+ if (!existsSync11(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
3825
3976
  if (!input.branches.length) throw new Error("At least one branch name required");
3826
3977
  const status = await detectGhStack(repoPath);
3827
3978
  if (!status.available) throw new Error(status.reason);
@@ -3888,7 +4039,7 @@ async function createPrStack(input, onSetupLine) {
3888
4039
  }
3889
4040
  }
3890
4041
  const claimed = new Set(threads.map((t) => t.worktreePath));
3891
- if (!claimed.has(bootstrap.worktreePath) && existsSync10(bootstrap.worktreePath)) {
4042
+ if (!claimed.has(bootstrap.worktreePath) && existsSync11(bootstrap.worktreePath)) {
3892
4043
  try {
3893
4044
  await removeWorktree(repoPath, bootstrap.worktreePath, {
3894
4045
  deleteBranch: bootstrap.branchName
@@ -3900,10 +4051,10 @@ async function createPrStack(input, onSetupLine) {
3900
4051
  }
3901
4052
 
3902
4053
  // src/diff/diff.ts
3903
- import { existsSync as existsSync11, mkdirSync as mkdirSync3, readFileSync as readFileSync8, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
3904
- import { dirname as dirname3, join as join10 } from "path";
4054
+ import { existsSync as existsSync12, mkdirSync as mkdirSync3, readFileSync as readFileSync9, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
4055
+ import { dirname as dirname3, join as join11 } from "path";
3905
4056
  async function inspectGitWorktree(worktreePath) {
3906
- if (!worktreePath || !existsSync11(worktreePath)) return "missing_worktree";
4057
+ if (!worktreePath || !existsSync12(worktreePath)) return "missing_worktree";
3907
4058
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
3908
4059
  reject: false
3909
4060
  });
@@ -3911,7 +4062,7 @@ async function inspectGitWorktree(worktreePath) {
3911
4062
  return "ok";
3912
4063
  }
3913
4064
  async function initializeGitRepository(worktreePath) {
3914
- if (!worktreePath || !existsSync11(worktreePath)) {
4065
+ if (!worktreePath || !existsSync12(worktreePath)) {
3915
4066
  throw new Error("Worktree not found");
3916
4067
  }
3917
4068
  const status = await inspectGitWorktree(worktreePath);
@@ -4047,11 +4198,11 @@ new file mode 100644
4047
4198
  };
4048
4199
  }
4049
4200
  async function untrackedPatch(worktreePath, path, maxHunk) {
4050
- const abs = join10(worktreePath, path);
4201
+ const abs = join11(worktreePath, path);
4051
4202
  try {
4052
4203
  const st = statSync2(abs);
4053
4204
  if (st.isFile() && st.size > maxHunk) {
4054
- const buf = readFileSync8(abs).subarray(0, maxHunk);
4205
+ const buf = readFileSync9(abs).subarray(0, maxHunk);
4055
4206
  return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
4056
4207
  }
4057
4208
  } catch {
@@ -4552,7 +4703,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
4552
4703
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
4553
4704
  assertSafeRelativePath(relativePath);
4554
4705
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
4555
- const abs = join10(worktreePath, relativePath);
4706
+ const abs = join11(worktreePath, relativePath);
4556
4707
  const st = statSync2(abs);
4557
4708
  if (!st.isFile()) {
4558
4709
  throw new Error(`Not a file: ${relativePath}`);
@@ -4562,7 +4713,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
4562
4713
  `File too large to upload (${st.size} bytes; max ${maxBytes})`
4563
4714
  );
4564
4715
  }
4565
- const buf = readFileSync8(abs);
4716
+ const buf = readFileSync9(abs);
4566
4717
  return {
4567
4718
  path: relativePath,
4568
4719
  contentBase64: buf.toString("base64"),
@@ -4572,12 +4723,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
4572
4723
  function readWorktreeFile(worktreePath, relativePath, opts) {
4573
4724
  assertSafeRelativePath(relativePath);
4574
4725
  const maxBytes = opts?.maxBytes ?? 2e5;
4575
- const abs = join10(worktreePath, relativePath);
4726
+ const abs = join11(worktreePath, relativePath);
4576
4727
  const st = statSync2(abs);
4577
4728
  if (!st.isFile()) {
4578
4729
  throw new Error(`Not a file: ${relativePath}`);
4579
4730
  }
4580
- const buf = readFileSync8(abs);
4731
+ const buf = readFileSync9(abs);
4581
4732
  if (isImageRelativePath(relativePath)) {
4582
4733
  const maxImageBytes = Math.max(maxBytes, 15e6);
4583
4734
  const truncated2 = buf.length > maxImageBytes;
@@ -4620,9 +4771,9 @@ function assertSafeRelativePath(relativePath) {
4620
4771
  }
4621
4772
  function writeWorktreeFile(worktreePath, relativePath, content) {
4622
4773
  assertSafeRelativePath(relativePath);
4623
- const abs = join10(worktreePath, relativePath);
4774
+ const abs = join11(worktreePath, relativePath);
4624
4775
  mkdirSync3(dirname3(abs), { recursive: true });
4625
- writeFileSync4(abs, content, "utf8");
4776
+ writeFileSync5(abs, content, "utf8");
4626
4777
  return { path: relativePath };
4627
4778
  }
4628
4779
  async function getDiffSummary(worktreePath, repoPath, opts) {
@@ -4747,9 +4898,9 @@ async function confirmLand(thread, opts) {
4747
4898
  }
4748
4899
 
4749
4900
  // src/skills/discover.ts
4750
- import { existsSync as existsSync12, readdirSync as readdirSync4, readFileSync as readFileSync9, statSync as statSync3 } from "fs";
4901
+ import { existsSync as existsSync13, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
4751
4902
  import { homedir } from "os";
4752
- import { join as join11 } from "path";
4903
+ import { join as join12 } from "path";
4753
4904
 
4754
4905
  // src/skills/bundled/long-running.ts
4755
4906
  var LONG_RUNNING_SKILL_COMMAND = "long-running";
@@ -4878,7 +5029,7 @@ function parseFrontmatter(content) {
4878
5029
  }
4879
5030
  function readSkill(skillMd, source) {
4880
5031
  try {
4881
- const content = readFileSync9(skillMd, "utf8");
5032
+ const content = readFileSync10(skillMd, "utf8");
4882
5033
  const { name: fmName, description } = parseFrontmatter(content);
4883
5034
  const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
4884
5035
  const name = fmName || dirName;
@@ -4897,7 +5048,7 @@ function readSkill(skillMd, source) {
4897
5048
  }
4898
5049
  }
4899
5050
  function scanSkillsDir(dir, source, out) {
4900
- if (!existsSync12(dir)) return;
5051
+ if (!existsSync13(dir)) return;
4901
5052
  let entries;
4902
5053
  try {
4903
5054
  entries = readdirSync4(dir);
@@ -4906,8 +5057,8 @@ function scanSkillsDir(dir, source, out) {
4906
5057
  }
4907
5058
  for (const entry of entries) {
4908
5059
  if (entry.startsWith(".")) continue;
4909
- const skillMd = join11(dir, entry, "SKILL.md");
4910
- if (!existsSync12(skillMd)) continue;
5060
+ const skillMd = join12(dir, entry, "SKILL.md");
5061
+ if (!existsSync13(skillMd)) continue;
4911
5062
  try {
4912
5063
  if (!statSync3(skillMd).isFile()) continue;
4913
5064
  } catch {
@@ -4918,7 +5069,7 @@ function scanSkillsDir(dir, source, out) {
4918
5069
  }
4919
5070
  }
4920
5071
  function scanClaudePluginSkills(pluginsRoot, out) {
4921
- if (!existsSync12(pluginsRoot)) return;
5072
+ if (!existsSync13(pluginsRoot)) return;
4922
5073
  const walk = (dir, depth, lookingForSkillsDir) => {
4923
5074
  if (depth > 7) return;
4924
5075
  let entries;
@@ -4928,12 +5079,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
4928
5079
  return;
4929
5080
  }
4930
5081
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
4931
- const skill = readSkill(join11(dir, "SKILL.md"), "cli");
5082
+ const skill = readSkill(join12(dir, "SKILL.md"), "cli");
4932
5083
  if (skill) out.push(skill);
4933
5084
  }
4934
5085
  for (const entry of entries) {
4935
5086
  if (entry === "node_modules" || entry === ".git") continue;
4936
- const full = join11(dir, entry);
5087
+ const full = join12(dir, entry);
4937
5088
  try {
4938
5089
  if (!statSync3(full).isDirectory()) continue;
4939
5090
  } catch {
@@ -4953,17 +5104,17 @@ function discoverSkills(worktreePath) {
4953
5104
  const home = homedir();
4954
5105
  const collected = [];
4955
5106
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
4956
- scanSkillsDir(join11(worktreePath, rel), "workspace", collected);
5107
+ scanSkillsDir(join12(worktreePath, rel), "workspace", collected);
4957
5108
  }
4958
5109
  for (const abs of [
4959
- join11(home, ".claude/skills"),
4960
- join11(home, ".cursor/skills"),
4961
- join11(home, ".sideboard/skills"),
4962
- join11(home, ".brightsy/skills")
5110
+ join12(home, ".claude/skills"),
5111
+ join12(home, ".cursor/skills"),
5112
+ join12(home, ".sideboard/skills"),
5113
+ join12(home, ".brightsy/skills")
4963
5114
  ]) {
4964
5115
  scanSkillsDir(abs, "user", collected);
4965
5116
  }
4966
- scanClaudePluginSkills(join11(home, ".claude/plugins"), collected);
5117
+ scanClaudePluginSkills(join12(home, ".claude/plugins"), collected);
4967
5118
  collected.push(...bundledSkills());
4968
5119
  const rank = {
4969
5120
  workspace: 0,
@@ -4989,7 +5140,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
4989
5140
  \u2026(truncated)` : body;
4990
5141
  }
4991
5142
  }
4992
- const raw = readFileSync9(skillPath, "utf8");
5143
+ const raw = readFileSync10(skillPath, "utf8");
4993
5144
  if (raw.startsWith("---")) {
4994
5145
  const end = raw.indexOf("\n---", 3);
4995
5146
  if (end >= 0) {
@@ -5082,26 +5233,26 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
5082
5233
  }
5083
5234
 
5084
5235
  // src/agents/instructions.ts
5085
- import { existsSync as existsSync14, readFileSync as readFileSync10, statSync as statSync4 } from "fs";
5086
- import { join as join13 } from "path";
5236
+ import { existsSync as existsSync15, readFileSync as readFileSync11, statSync as statSync4 } from "fs";
5237
+ import { join as join14 } from "path";
5087
5238
 
5088
5239
  // src/skills/detached-job-path.ts
5089
- import { existsSync as existsSync13 } from "fs";
5090
- import { dirname as dirname4, join as join12 } from "path";
5240
+ import { existsSync as existsSync14 } from "fs";
5241
+ import { dirname as dirname4, join as join13 } from "path";
5091
5242
  import { fileURLToPath } from "url";
5092
5243
  function packagedDetachedJobPath() {
5093
5244
  const dir = packagedMcpDir();
5094
5245
  if (!dir) return null;
5095
- const script = join12(dir, "scripts", "detached-job.js");
5096
- return existsSync13(script) ? script : null;
5246
+ const script = join13(dir, "scripts", "detached-job.js");
5247
+ return existsSync14(script) ? script : null;
5097
5248
  }
5098
5249
  function resolveDetachedJobScript() {
5099
5250
  const packaged = packagedDetachedJobPath();
5100
5251
  if (packaged) return packaged;
5101
5252
  let dir = dirname4(fileURLToPath(import.meta.url));
5102
5253
  for (let i = 0; i < 8; i++) {
5103
- const candidate = join12(dir, "scripts", "detached-job.js");
5104
- if (existsSync13(candidate)) return candidate;
5254
+ const candidate = join13(dir, "scripts", "detached-job.js");
5255
+ if (existsSync14(candidate)) return candidate;
5105
5256
  const parent = dirname4(dir);
5106
5257
  if (parent === dir) break;
5107
5258
  dir = parent;
@@ -5403,8 +5554,8 @@ async function syncThreadBranchFromGit(threadId) {
5403
5554
 
5404
5555
  // src/store/schedules.ts
5405
5556
  import { randomUUID as randomUUID4 } from "crypto";
5406
- import { existsSync as existsSync15, readFileSync as readFileSync11 } from "fs";
5407
- import { join as join14 } from "path";
5557
+ import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
5558
+ import { join as join15 } from "path";
5408
5559
  import { Cron } from "croner";
5409
5560
  var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
5410
5561
  var UNIT_MS = {
@@ -5414,7 +5565,7 @@ var UNIT_MS = {
5414
5565
  d: 864e5
5415
5566
  };
5416
5567
  function schedulesPath() {
5417
- return join14(appDataDir(), "schedules.json");
5568
+ return join15(appDataDir(), "schedules.json");
5418
5569
  }
5419
5570
  function parseDurationMs(every) {
5420
5571
  const m = every.trim().match(DURATION_RE);
@@ -5514,9 +5665,9 @@ function normalizeTask(raw) {
5514
5665
  }
5515
5666
  function readAll() {
5516
5667
  const path = schedulesPath();
5517
- if (!existsSync15(path)) return [];
5668
+ if (!existsSync16(path)) return [];
5518
5669
  try {
5519
- const parsed = JSON.parse(readFileSync11(path, "utf8"));
5670
+ const parsed = JSON.parse(readFileSync12(path, "utf8"));
5520
5671
  if (!Array.isArray(parsed)) return [];
5521
5672
  return parsed.map((row) => {
5522
5673
  try {
@@ -5639,7 +5790,7 @@ function formatScheduledPrompt(name, prompt) {
5639
5790
  ${prompt}`;
5640
5791
  }
5641
5792
  async function defaultDeps() {
5642
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-256DFPSX.js");
5793
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-3FWEKDAQ.js");
5643
5794
  const orch = getOrchestrator2();
5644
5795
  return {
5645
5796
  findThread: (id) => findThreadByRef(id),
@@ -5879,7 +6030,7 @@ var Orchestrator = class {
5879
6030
  }
5880
6031
  continue;
5881
6032
  }
5882
- if (!existsSync16(thread.worktreePath)) {
6033
+ if (!existsSync17(thread.worktreePath)) {
5883
6034
  setStatus(thread.id, "broken", "Worktree missing on disk");
5884
6035
  this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
5885
6036
  continue;
@@ -5898,7 +6049,7 @@ var Orchestrator = class {
5898
6049
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
5899
6050
  });
5900
6051
  }
5901
- const { autoCleanupOrphansEnabled } = await import("./app-settings-J3JBCUOT.js");
6052
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-VRQI3FIE.js");
5902
6053
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
5903
6054
  await cleanupOrphanWorktrees({ repoPaths });
5904
6055
  }
@@ -6138,7 +6289,7 @@ var Orchestrator = class {
6138
6289
  }
6139
6290
  await setup;
6140
6291
  if (skipSetup) return;
6141
- const { autoRunAfterSetupEnabled } = await import("./app-settings-J3JBCUOT.js");
6292
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-VRQI3FIE.js");
6142
6293
  if (autoRunAfterSetupEnabled()) {
6143
6294
  try {
6144
6295
  await this.startDev(threadId);
@@ -6149,21 +6300,11 @@ var Orchestrator = class {
6149
6300
  /** Run workspace setup after a new worktree is created (no-op if none configured). */
6150
6301
  async runSetupAfterCreate(threadId) {
6151
6302
  try {
6152
- await this.runSetup(threadId);
6303
+ await this.runSetup(threadId, { stampLastError: false });
6153
6304
  } catch (err) {
6154
6305
  const message = err instanceof Error ? err.message : String(err);
6155
6306
  if (/no setup script/i.test(message)) return;
6156
6307
  if (/already running/i.test(message)) return;
6157
- const live = readThread(threadId);
6158
- if (!shouldStampSetupLastError({
6159
- turnInFlight: this.activeTurns.has(threadId) || this.startingTurns.has(threadId),
6160
- status: live?.status
6161
- })) {
6162
- return;
6163
- }
6164
- updateThread(threadId, {
6165
- lastError: `Setup failed: ${message}`
6166
- });
6167
6308
  }
6168
6309
  }
6169
6310
  listWorkspaces() {
@@ -6446,7 +6587,7 @@ var Orchestrator = class {
6446
6587
  }
6447
6588
  const isBrightsy = fresh.agent === "brightsy";
6448
6589
  const isOrchestration = isOrchestratorThread(fresh);
6449
- const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-J3JBCUOT.js");
6590
+ const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-VRQI3FIE.js");
6450
6591
  const gitAuthMode = getGithubGitAuthMode();
6451
6592
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
6452
6593
  githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
@@ -6552,7 +6693,7 @@ var Orchestrator = class {
6552
6693
  if (!this.stoppedTurns.has(threadId) && this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
6553
6694
  const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
6554
6695
  if (sessionId) {
6555
- const { recoverFinishedCursorRun } = await import("./cursor-recover-NOQYOFRF.js");
6696
+ const { recoverFinishedCursorRun } = await import("./cursor-recover-L5MD6MBO.js");
6556
6697
  for (let i = 0; i < 8; i++) {
6557
6698
  const recovered = recoverFinishedCursorRun({
6558
6699
  agentId: sessionId,
@@ -6942,7 +7083,16 @@ var Orchestrator = class {
6942
7083
  getActiveRuns(threadRef) {
6943
7084
  return this.requireThread(threadRef).activeRuns ?? [];
6944
7085
  }
6945
- async runSetup(threadRef) {
7086
+ getSetupLog(threadRef) {
7087
+ const thread = this.getThread(threadRef);
7088
+ if (!thread) return readSetupLog(threadRef);
7089
+ const snap = readSetupLog(thread.id);
7090
+ if (snap.running && !this.processes.has(`${thread.id}:setup`)) {
7091
+ return { ...snap, running: false };
7092
+ }
7093
+ return snap;
7094
+ }
7095
+ async runSetup(threadRef, opts) {
6946
7096
  const thread = this.requireThread(threadRef);
6947
7097
  this.assertNotGlobal(thread, "Setup");
6948
7098
  const key = `${thread.id}:setup`;
@@ -6955,34 +7105,49 @@ var Orchestrator = class {
6955
7105
  startedAt: (/* @__PURE__ */ new Date()).toISOString(),
6956
7106
  kill: () => abort.abort()
6957
7107
  });
7108
+ beginSetupLog(thread.id);
6958
7109
  this.emit({ type: "setup_started", threadId: thread.id });
7110
+ let finished = false;
7111
+ const finish = (exitCode, source) => {
7112
+ if (finished) return;
7113
+ finished = true;
7114
+ finishSetupLog(thread.id, exitCode, source);
7115
+ this.emit({ type: "setup_finished", threadId: thread.id, exitCode });
7116
+ };
6959
7117
  try {
6960
7118
  const setup = await runWorkspaceSetup(
6961
7119
  thread.repoPath,
6962
7120
  thread.worktreePath,
6963
7121
  (line) => {
7122
+ appendSetupLog(thread.id, line);
6964
7123
  this.emit({ type: "setup_output", threadId: thread.id, line });
6965
7124
  },
6966
7125
  { signal: abort.signal }
6967
7126
  );
6968
7127
  if (!setup.ran) {
6969
- throw new Error(
6970
- "No setup script in .sideboard/settings.toml, .conductor/settings.toml, .cursor/worktrees.json, or script/setup (bin/setup, scripts/setup)"
6971
- );
7128
+ const line = "No setup script in .sideboard/settings.toml, .conductor/settings.toml, .cursor/worktrees.json, or script/setup (bin/setup, scripts/setup)";
7129
+ appendSetupLog(thread.id, line);
7130
+ this.emit({ type: "setup_output", threadId: thread.id, line });
7131
+ finish(null, null);
7132
+ throw new Error(line);
6972
7133
  }
6973
7134
  if (setup.exitCode !== 0 && setup.exitCode !== null) {
6974
7135
  const live = readThread(thread.id);
6975
- if (shouldStampSetupLastError({
7136
+ if ((opts?.stampLastError ?? true) && shouldStampSetupLastError({
6976
7137
  turnInFlight: this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id),
6977
- status: live?.status
7138
+ status: live?.status,
7139
+ hasQueuedPrompt: Boolean(live?.queue?.length)
6978
7140
  })) {
6979
7141
  updateThread(thread.id, {
6980
7142
  lastError: `Setup exited ${setup.exitCode}`
6981
7143
  });
6982
7144
  }
6983
7145
  }
6984
- this.emit({ type: "setup_finished", threadId: thread.id, exitCode: setup.exitCode });
7146
+ finish(setup.exitCode, setup.source);
6985
7147
  return { exitCode: setup.exitCode, source: setup.source };
7148
+ } catch (err) {
7149
+ finish(null, null);
7150
+ throw err;
6986
7151
  } finally {
6987
7152
  this.processes.delete(key);
6988
7153
  }
@@ -7309,7 +7474,7 @@ var Orchestrator = class {
7309
7474
  updateThread(thread.id, { title: meta.title });
7310
7475
  }
7311
7476
  }
7312
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-J3JBCUOT.js");
7477
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-VRQI3FIE.js");
7313
7478
  const latest = this.requireThread(thread.id);
7314
7479
  if (!shouldAutoArchiveOnPrMerge({
7315
7480
  previousPrState: prevState || null,
@@ -7626,7 +7791,7 @@ var Orchestrator = class {
7626
7791
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
7627
7792
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
7628
7793
  try {
7629
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-NECIQTAO.js");
7794
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-MQYNZXUK.js");
7630
7795
  await ensureWorkspace2(thread.repoPath);
7631
7796
  } catch {
7632
7797
  }
@@ -7653,7 +7818,7 @@ var Orchestrator = class {
7653
7818
  await runArchiveScript(thread.repoPath, thread.worktreePath);
7654
7819
  } catch {
7655
7820
  }
7656
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-J3JBCUOT.js");
7821
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-VRQI3FIE.js");
7657
7822
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
7658
7823
  await removeWorktree(thread.repoPath, thread.worktreePath, {
7659
7824
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -7668,19 +7833,19 @@ var Orchestrator = class {
7668
7833
  throw new Error("Thread is not archived");
7669
7834
  }
7670
7835
  if (isGlobalThread(thread)) {
7671
- const { globalAgentCwd } = await import("./paths-QCI3MTO5.js");
7836
+ const { globalAgentCwd } = await import("./paths-RRCLNSJB.js");
7672
7837
  updateThread(thread.id, { worktreePath: globalAgentCwd() });
7673
7838
  const restored2 = setStatus(thread.id, "idle");
7674
7839
  this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
7675
7840
  return restored2;
7676
7841
  }
7677
- if (!existsSync16(thread.worktreePath)) {
7842
+ if (!existsSync17(thread.worktreePath)) {
7678
7843
  if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
7679
7844
  throw new Error(
7680
7845
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
7681
7846
  );
7682
7847
  }
7683
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-HTUM35NT.js");
7848
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-PEWDAX5O.js");
7684
7849
  const slug = thread.worktreePath.split("/").pop();
7685
7850
  const dest = thread.worktreePath;
7686
7851
  await withRepoGitLock(thread.repoPath, async () => {
@@ -7790,7 +7955,7 @@ async function startOrchestration(opts) {
7790
7955
  sourceRef: "default",
7791
7956
  ...createOpts
7792
7957
  }).catch(async () => {
7793
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-HTUM35NT.js");
7958
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-PEWDAX5O.js");
7794
7959
  const repo = await resolveRepoRoot2(repoPath);
7795
7960
  const def = await resolveDefaultBranch2(repo);
7796
7961
  return orch.createThread({
@@ -7800,7 +7965,7 @@ async function startOrchestration(opts) {
7800
7965
  repoPath: repo
7801
7966
  });
7802
7967
  });
7803
- const { updateThread: upd } = await import("./thread-store-57ZLHR3A.js");
7968
+ const { updateThread: upd } = await import("./thread-store-MVQU6HPJ.js");
7804
7969
  const updated = upd(thread.id, {
7805
7970
  sourceType: "orchestration",
7806
7971
  sourceRef: goal
@@ -7833,7 +7998,6 @@ export {
7833
7998
  findBoardPr,
7834
7999
  assembleHomeBoard,
7835
8000
  HOME_BOARD_AGENT_HINT,
7836
- listLinearIssues,
7837
8001
  readTurnLive,
7838
8002
  resolveScheduleThreadId,
7839
8003
  listSchedules,