@sideboard-ai/core 0.1.217 → 0.1.218

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 (59) hide show
  1. package/dist/{abletime-QGGYL2G4.js → abletime-BF253OZT.js} +5 -4
  2. package/dist/{abletime-GDZLZRMY.js → abletime-D6773P33.js} +5 -5
  3. package/dist/{abletime-oauth-F335TWKY.js → abletime-oauth-H4672PRH.js} +4 -3
  4. package/dist/{abletime-oauth-3X3BAPTF.js → abletime-oauth-KQPVVBKA.js} +4 -4
  5. package/dist/{abletime-rest-PLJVY3H3.js → abletime-rest-DAFPXZ7H.js} +4 -4
  6. package/dist/{abletime-rest-LAGTPAJL.js → abletime-rest-OPEVV3XC.js} +4 -3
  7. package/dist/agents/cursor-runner.js +5 -5
  8. package/dist/{agents-WBDDLRBY.js → agents-NWJ7DFJD.js} +8 -7
  9. package/dist/{agents-HETHRRZJ.js → agents-YABJUV3V.js} +9 -9
  10. package/dist/{app-settings-XCRNCEEE.js → app-settings-5RQMQKSB.js} +2 -1
  11. package/dist/{app-settings-2TN3WLZV.js → app-settings-V2BBCX2H.js} +2 -2
  12. package/dist/{chunk-MN6YUD4O.js → chunk-3NWUHXU3.js} +3 -3
  13. package/dist/{chunk-G4TANQC3.js → chunk-646I442S.js} +5 -5
  14. package/dist/{chunk-FNQNJOHY.js → chunk-ABOBTSO6.js} +4 -1
  15. package/dist/{chunk-YVE4PXCJ.js → chunk-CLI5DVU4.js} +2 -2
  16. package/dist/{chunk-7MTVRNP4.js → chunk-FSIJGLSV.js} +1173 -1186
  17. package/dist/{chunk-LS6TSOCE.js → chunk-HSYE5ID6.js} +5 -5
  18. package/dist/{chunk-UFHNSFAS.js → chunk-HVUVQXZ2.js} +5 -1
  19. package/dist/{chunk-SALM35KD.js → chunk-IILG7DPX.js} +5 -5
  20. package/dist/{chunk-D2IKXMF3.js → chunk-JWBPSD7Q.js} +453 -289
  21. package/dist/{chunk-NI243N27.js → chunk-KTZESHYH.js} +15 -7
  22. package/dist/{chunk-KFD2OXCE.js → chunk-MW57SKKR.js} +19 -6
  23. package/dist/{chunk-XYKVRRC2.js → chunk-NFWPDEN4.js} +15 -7
  24. package/dist/{chunk-FNGXKY5W.js → chunk-OPYBLX4V.js} +19 -6
  25. package/dist/{chunk-QQKDGPUI.js → chunk-PO4M4JAJ.js} +1 -1
  26. package/dist/{chunk-2M5B7YNY.js → chunk-RRW2XWAY.js} +2 -2
  27. package/dist/{chunk-REZRGCKV.js → chunk-SOGGKYFV.js} +3 -3
  28. package/dist/{chunk-C32SBNA3.js → chunk-SRFFIFW6.js} +457 -294
  29. package/dist/{chunk-3OHR73VK.js → chunk-SVXIJ2IC.js} +1 -1
  30. package/dist/{chunk-SYFVUF2C.js → chunk-SZJZEFTY.js} +1 -1
  31. package/dist/{chunk-42IULNIY.js → chunk-THLVCXLF.js} +3 -3
  32. package/dist/{chunk-JZHRZ3DR.js → chunk-TQBUXKIB.js} +5 -5
  33. package/dist/chunk-WWUABK6B.js +56 -0
  34. package/dist/{chunk-DFTVZEZY.js → chunk-XRHTRXZN.js} +1051 -1050
  35. package/dist/{chunk-BTC2D6LS.js → chunk-Y5JES2VV.js} +3 -51
  36. package/dist/{connected-teams-WK47ATT7.js → connected-teams-LX5DLL2I.js} +3 -2
  37. package/dist/{connected-teams-PU4AMFNA.js → connected-teams-PQETXUWV.js} +3 -2
  38. package/dist/{coordinator-prompt-FQX6ALAI.js → coordinator-prompt-5V7GEPBG.js} +6 -6
  39. package/dist/{coordinator-prompt-LE2GQZ2X.js → coordinator-prompt-J4QSNTKE.js} +6 -5
  40. package/dist/{global-workspace-6P236KKG.js → global-workspace-4TEMLESD.js} +6 -6
  41. package/dist/{global-workspace-KT3FRHZL.js → global-workspace-XPTFHMKL.js} +6 -5
  42. package/dist/index.cjs +1027 -821
  43. package/dist/index.d.cts +10 -1
  44. package/dist/index.d.ts +10 -1
  45. package/dist/index.js +22 -18
  46. package/dist/mcp/run-stdio.cjs +1838 -1651
  47. package/dist/mcp/run-stdio.js +16 -14
  48. package/dist/{orchestrator-WVZPTHBV.js → orchestrator-HKW3VLGX.js} +10 -10
  49. package/dist/{orchestrator-MI7A5DQZ.js → orchestrator-SWRTYFHX.js} +9 -8
  50. package/dist/{run-EBWL2Q4N.js → run-QDZCTP4Y.js} +2 -1
  51. package/dist/{run-CAGKZLHA.js → run-UEQM4JMZ.js} +2 -1
  52. package/dist/{workspaces-KM7KTLVO.js → workspaces-2HQP654Q.js} +6 -5
  53. package/dist/{workspaces-R5LJCJRB.js → workspaces-BCBBMMXB.js} +6 -6
  54. package/dist/{worktree-MDMTCAHX.js → worktree-7V67XTEO.js} +5 -5
  55. package/dist/{worktree-VXRI7LYM.js → worktree-I573UOPD.js} +5 -4
  56. package/dist/{worktree-exclude-N5X5I422.js → worktree-exclude-K7QK4RI5.js} +3 -2
  57. package/dist/{worktree-exclude-X54WSOXM.js → worktree-exclude-L32WEBX6.js} +3 -2
  58. package/package.json +1 -1
  59. package/dist/{chunk-L5CIEBLR.js → chunk-EWHJNJHV.js} +3 -3
@@ -24,7 +24,7 @@ import {
24
24
  resolveQuotaFallbackAgent,
25
25
  stripBrightsyNdjsonNoise,
26
26
  toolDescription
27
- } from "./chunk-DFTVZEZY.js";
27
+ } from "./chunk-XRHTRXZN.js";
28
28
  import {
29
29
  SLACK_REPLY_FORMATTING,
30
30
  addWorkspace,
@@ -47,7 +47,7 @@ import {
47
47
  stageAbsolutePathsAsAttachments,
48
48
  stageBuffersAsAttachments,
49
49
  syncWorkspacesFromThreads
50
- } from "./chunk-FNGXKY5W.js";
50
+ } from "./chunk-OPYBLX4V.js";
51
51
  import {
52
52
  addPrStackLayer,
53
53
  allocateTeamName,
@@ -81,7 +81,6 @@ import {
81
81
  mergeAgentGitAuthEnv,
82
82
  mergePr,
83
83
  normalizeWorktreePath,
84
- originGhRepoEnv,
85
84
  pushBranch,
86
85
  removeWorktree,
87
86
  resolveAgentGitAuthEnv,
@@ -97,7 +96,7 @@ import {
97
96
  worktreeDisplayLabelForGroup,
98
97
  worktreeNameFromPath,
99
98
  worktreeSlugForTicket
100
- } from "./chunk-NI243N27.js";
99
+ } from "./chunk-KTZESHYH.js";
101
100
  import {
102
101
  ATTACHMENTS_DIR,
103
102
  DETACHED_JOBS_DIR,
@@ -106,7 +105,7 @@ import {
106
105
  } from "./chunk-6K64FJDD.js";
107
106
  import {
108
107
  ensureWorktreeSideboardIgnored
109
- } from "./chunk-QQKDGPUI.js";
108
+ } from "./chunk-PO4M4JAJ.js";
110
109
  import {
111
110
  httpFetch
112
111
  } from "./chunk-N7WZ6NIN.js";
@@ -129,7 +128,7 @@ import {
129
128
  shouldRetryFailedAgentTurn,
130
129
  summarizeTurnStderr,
131
130
  turnFailChatText
132
- } from "./chunk-JZHRZ3DR.js";
131
+ } from "./chunk-TQBUXKIB.js";
133
132
  import {
134
133
  HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT,
135
134
  applyTurnUsage,
@@ -164,10 +163,7 @@ import {
164
163
  updateAdvancedSettings,
165
164
  usageOnLimit,
166
165
  writeSecureJson
167
- } from "./chunk-L5CIEBLR.js";
168
- import {
169
- stripNestedElectronEnv
170
- } from "./chunk-4TR3HZFT.js";
166
+ } from "./chunk-EWHJNJHV.js";
171
167
  import {
172
168
  examplePrefixedBranch,
173
169
  sanitizeGitBranchPrefix
@@ -210,7 +206,10 @@ import {
210
206
  git,
211
207
  resolveGitDirsForLockRecovery,
212
208
  run
213
- } from "./chunk-UFHNSFAS.js";
209
+ } from "./chunk-HVUVQXZ2.js";
210
+ import {
211
+ stripNestedElectronEnv
212
+ } from "./chunk-4TR3HZFT.js";
214
213
 
215
214
  // src/orchestrator/orchestrator.ts
216
215
  import { EventEmitter } from "events";
@@ -483,7 +482,7 @@ async function continueSourceThread(threadId, prompt) {
483
482
  await continueOnReply(threadId, prompt);
484
483
  return;
485
484
  }
486
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-WVZPTHBV.js");
485
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-HKW3VLGX.js");
487
486
  await getOrchestrator2().send(threadId, prompt);
488
487
  } catch {
489
488
  }
@@ -749,20 +748,104 @@ import { existsSync as existsSync19 } from "fs";
749
748
  import { createInterface } from "readline";
750
749
  import { execa } from "execa";
751
750
 
751
+ // src/agents/turn-trace.ts
752
+ import { appendFileSync } from "fs";
753
+ import { join as join4 } from "path";
754
+ function traceTurn(phase, extra) {
755
+ try {
756
+ const line = `${JSON.stringify({ t: (/* @__PURE__ */ new Date()).toISOString(), phase, ...extra })}
757
+ `;
758
+ appendFileSync(join4(appDataDir(), "turn-spawn.log"), line);
759
+ } catch {
760
+ }
761
+ }
762
+ async function withTimeout(promise, ms, label) {
763
+ let timer;
764
+ try {
765
+ return await Promise.race([
766
+ promise,
767
+ new Promise((_, reject) => {
768
+ timer = setTimeout(
769
+ () => reject(new Error(`${label} timed out after ${ms}ms`)),
770
+ ms
771
+ );
772
+ })
773
+ ]);
774
+ } finally {
775
+ if (timer) clearTimeout(timer);
776
+ }
777
+ }
778
+
779
+ // src/hook/agent-host-env.ts
780
+ import { delimiter } from "path";
781
+ var DROP_EXACT = /* @__PURE__ */ new Set([
782
+ "NODE_PATH",
783
+ "NODE_ENV_ELECTRON_VITE",
784
+ "INIT_CWD",
785
+ "npm_command",
786
+ "npm_execpath",
787
+ "npm_node_execpath",
788
+ "npm_lifecycle_event",
789
+ "npm_lifecycle_script",
790
+ "PNPM_SCRIPT_SRC_DIR",
791
+ "PNPM_STORE_DIR",
792
+ "PORT",
793
+ "SIDEBOARD_ROOT_PATH",
794
+ "SIDEBOARD_IS_LOCAL",
795
+ "SIDEBOARD_WORKSPACE_PATH",
796
+ "SIDEBOARD_WORKSPACE_NAME",
797
+ "SIDEBOARD_PORT",
798
+ "CONDUCTOR_ROOT_PATH",
799
+ "CONDUCTOR_IS_LOCAL",
800
+ "CONDUCTOR_WORKSPACE_PATH",
801
+ "CONDUCTOR_WORKSPACE_NAME",
802
+ "CONDUCTOR_PORT",
803
+ "CONDUCTOR_DEFAULT_BRANCH",
804
+ "SIDEBOARD_DEFAULT_BRANCH"
805
+ ]);
806
+ var DROP_PREFIXES = [
807
+ "npm_package_",
808
+ "npm_config_",
809
+ "PNPM_",
810
+ "SIDEBOARD_PORT_",
811
+ "CONDUCTOR_PORT_"
812
+ ];
813
+ var HOST_PATH_NOISE = /(?:^|\/)node_modules\/\.bin(?:\/|$)|node-gyp-bin|electron-vite/i;
814
+ function isAgentHostEnvKey(key) {
815
+ if (DROP_EXACT.has(key)) return true;
816
+ return DROP_PREFIXES.some((prefix) => key.startsWith(prefix));
817
+ }
818
+ function stripHostToolingPath(pathValue) {
819
+ if (!pathValue?.trim()) return "";
820
+ return pathValue.split(delimiter).filter((part) => part && !HOST_PATH_NOISE.test(part.replace(/\\/g, "/"))).join(delimiter);
821
+ }
822
+ function sanitizeAgentHostEnv(env, cwd) {
823
+ for (const key of Object.keys(env)) {
824
+ if (isAgentHostEnvKey(key)) delete env[key];
825
+ }
826
+ env.PATH = stripHostToolingPath(env.PATH);
827
+ const worktree = cwd?.trim();
828
+ if (worktree) {
829
+ env.PWD = worktree;
830
+ env.INIT_CWD = worktree;
831
+ }
832
+ return env;
833
+ }
834
+
752
835
  // src/hook/worktree-pkg-cache.ts
753
836
  import { existsSync as existsSync3, mkdirSync } from "fs";
754
- import { join as join4 } from "path";
837
+ import { join as join5 } from "path";
755
838
  var WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
756
839
  function worktreePkgCacheRoot(worktreePath) {
757
- return join4(worktreePath, WORKTREE_PKG_CACHE_REL);
840
+ return join5(worktreePath, WORKTREE_PKG_CACHE_REL);
758
841
  }
759
842
  function worktreePkgCacheEnv(worktreePath) {
760
843
  const root = worktreePkgCacheRoot(worktreePath);
761
- const store = join4(root, "pnpm-store");
762
- const pnpmCache = join4(root, "pnpm");
763
- const npmCache = join4(root, "npm");
764
- const nodeGyp = join4(root, "node-gyp");
765
- const electron = join4(root, "electron");
844
+ const store = join5(root, "pnpm-store");
845
+ const pnpmCache = join5(root, "pnpm");
846
+ const npmCache = join5(root, "npm");
847
+ const nodeGyp = join5(root, "node-gyp");
848
+ const electron = join5(root, "electron");
766
849
  return {
767
850
  npm_config_store_dir: store,
768
851
  PNPM_STORE_DIR: store,
@@ -817,9 +900,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
817
900
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
818
901
  );
819
902
  }
820
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-6P236KKG.js");
903
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-4TEMLESD.js");
821
904
  if (isGlobalThread2(thread)) {
822
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-FQX6ALAI.js");
905
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-5V7GEPBG.js");
823
906
  ensureGlobalCoordinatorCwd2(
824
907
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
825
908
  );
@@ -828,26 +911,54 @@ async function spawnAgentTurn(thread, input, onEvent) {
828
911
  assertOrchestratorCapableAgent(thread.agent);
829
912
  }
830
913
  const adapter = getAdapter(thread.agent);
831
- const cmd = await adapter.buildTurn(thread, input);
914
+ const orch = isOrchestratorThread(thread);
915
+ traceTurn("spawn.buildTurn.start", {
916
+ threadId: thread.id,
917
+ agent: thread.agent,
918
+ orch,
919
+ cwd: thread.worktreePath
920
+ });
921
+ const cmd = await withTimeout(
922
+ adapter.buildTurn(thread, input),
923
+ 2e4,
924
+ "buildTurn"
925
+ );
926
+ traceTurn("spawn.buildTurn.done", { file: cmd.file, cwd: cmd.cwd });
832
927
  if (cmd.cwd !== thread.worktreePath) {
833
928
  throw new Error(
834
929
  `Agent cwd must be the thread worktree (got ${cmd.cwd}, expected ${thread.worktreePath})`
835
930
  );
836
931
  }
837
932
  const env = childEnvWithAppSettings(cmd.env);
933
+ sanitizeAgentHostEnv(env, cmd.cwd);
934
+ ensureAgentPath(env);
838
935
  applyPromptCacheTtlEnv(thread.agent, env);
839
936
  applyAgentRunnerHeapEnv(env);
840
- if (!isOrchestratorThread(thread)) {
937
+ if (!orch) {
841
938
  applyWorktreePkgCacheEnv(env, thread.worktreePath);
842
939
  }
843
940
  try {
844
- if (isOrchestratorThread(thread)) {
845
- mergeAgentGitAuthEnv(env, await resolveAgentGitAuthEnv(env));
846
- } else {
847
- mergeAgentGitAuthEnv(env, await originGhRepoEnv(thread.worktreePath, { env }));
941
+ traceTurn("spawn.gitAuth.start");
942
+ mergeAgentGitAuthEnv(
943
+ env,
944
+ await withTimeout(
945
+ resolveAgentGitAuthEnv(env, { cwd: thread.worktreePath }),
946
+ 8e3,
947
+ "gitAuth"
948
+ )
949
+ );
950
+ if (!orch) {
951
+ const slug = await withTimeout(
952
+ resolveGithubRepoSlug(thread.worktreePath),
953
+ 8e3,
954
+ "resolveGithubRepoSlug"
955
+ );
956
+ if (slug) env.GH_REPO = slug;
848
957
  }
958
+ traceTurn("spawn.gitAuth.done", { ghRepo: env.GH_REPO ?? null });
849
959
  } catch (err) {
850
960
  const detail = err instanceof Error ? err.message : String(err);
961
+ traceTurn("spawn.gitAuth.fail", { detail });
851
962
  console.warn(`[sideboard] git auth env failed (${thread.worktreePath}): ${detail}`);
852
963
  }
853
964
  const child = execa(cmd.file, cmd.args, {
@@ -860,6 +971,7 @@ async function spawnAgentTurn(thread, input, onEvent) {
860
971
  // so Claude doesn't wait ~3s for an empty pipe.
861
972
  stdin: cmd.stdin != null ? "pipe" : "ignore"
862
973
  });
974
+ traceTurn("spawn.execa", { pid: child.pid ?? null, file: cmd.file });
863
975
  if (cmd.stdin != null && child.stdin) {
864
976
  child.stdin.write(cmd.stdin);
865
977
  child.stdin.end();
@@ -1091,14 +1203,14 @@ import {
1091
1203
  readFileSync as readFileSync4
1092
1204
  } from "fs";
1093
1205
  import { createServer } from "net";
1094
- import { basename, dirname as dirname2, join as join6 } from "path";
1206
+ import { basename, dirname as dirname2, join as join7 } from "path";
1095
1207
  import { execa as execa2 } from "execa";
1096
1208
  import { createInterface as createInterface2 } from "readline";
1097
1209
 
1098
1210
  // src/review/request-review.ts
1099
1211
  import { randomUUID as randomUUID2 } from "crypto";
1100
1212
  import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
1101
- import { dirname, join as join5 } from "path";
1213
+ import { dirname, join as join6 } from "path";
1102
1214
 
1103
1215
  // src/threads/chat-tabs.ts
1104
1216
  import { randomUUID } from "crypto";
@@ -1889,12 +2001,12 @@ function readTextIfPresent(abs) {
1889
2001
  }
1890
2002
  }
1891
2003
  function readLocalGuidelines(worktreePath) {
1892
- const localAbs = join5(worktreePath, REVIEW_REQUEST_PATH);
2004
+ const localAbs = join6(worktreePath, REVIEW_REQUEST_PATH);
1893
2005
  const localContent = readTextIfPresent(localAbs);
1894
2006
  if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
1895
2007
  return { path: REVIEW_REQUEST_PATH, content: localContent };
1896
2008
  }
1897
- const legacyAbs = join5(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
2009
+ const legacyAbs = join6(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
1898
2010
  const legacyContent = readTextIfPresent(legacyAbs);
1899
2011
  if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
1900
2012
  return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
@@ -1918,7 +2030,7 @@ function contextGuidelines(content, source) {
1918
2030
  };
1919
2031
  }
1920
2032
  function writeContextGuidelines(worktreePath, content) {
1921
- const abs = join5(worktreePath, CONTEXT_REVIEW_PATH);
2033
+ const abs = join6(worktreePath, CONTEXT_REVIEW_PATH);
1922
2034
  mkdirSync2(dirname(abs), { recursive: true });
1923
2035
  const body = content.endsWith("\n") ? content : `${content}
1924
2036
  `;
@@ -1926,19 +2038,19 @@ function writeContextGuidelines(worktreePath, content) {
1926
2038
  return body;
1927
2039
  }
1928
2040
  function readSideboardReview(worktreePath, repoPath) {
1929
- const fromWorktree = readTextIfPresent(join5(worktreePath, REPO_REVIEW_PATH));
2041
+ const fromWorktree = readTextIfPresent(join6(worktreePath, REPO_REVIEW_PATH));
1930
2042
  if (fromWorktree) return fromWorktree;
1931
2043
  const repo = repoPath?.replace(/\/+$/, "");
1932
2044
  const wt = worktreePath.replace(/\/+$/, "");
1933
2045
  if (!repo || repo === wt) return null;
1934
- return readTextIfPresent(join5(repo, REPO_REVIEW_PATH));
2046
+ return readTextIfPresent(join6(repo, REPO_REVIEW_PATH));
1935
2047
  }
1936
2048
  function ensureReviewGuidelinesFile(worktreePath, repoPath) {
1937
- const skillContent = readTextIfPresent(join5(worktreePath, REVIEW_SKILL_PATH));
2049
+ const skillContent = readTextIfPresent(join6(worktreePath, REVIEW_SKILL_PATH));
1938
2050
  if (skillContent) {
1939
2051
  return { ...skillGuidelines(skillContent, "skill"), wrote: false };
1940
2052
  }
1941
- const contextContent = readTextIfPresent(join5(worktreePath, CONTEXT_REVIEW_PATH));
2053
+ const contextContent = readTextIfPresent(join6(worktreePath, CONTEXT_REVIEW_PATH));
1942
2054
  if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
1943
2055
  return { ...contextGuidelines(contextContent, "local"), wrote: false };
1944
2056
  }
@@ -1976,7 +2088,7 @@ function buildReviewRequestAttachment(content, opts) {
1976
2088
  };
1977
2089
  }
1978
2090
  function readExistingReviewRequestFile(worktreePath) {
1979
- return readTextIfPresent(join5(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent(join5(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent(join5(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent(join5(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent(join5(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
2091
+ return readTextIfPresent(join6(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent(join6(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent(join6(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent(join6(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent(join6(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
1980
2092
  }
1981
2093
  async function requestReview(threadRef, send) {
1982
2094
  const from = findThreadByRef(threadRef);
@@ -2011,7 +2123,7 @@ function matchSimpleGlob(pattern, name) {
2011
2123
  return new RegExp(`^${escaped}$`).test(name);
2012
2124
  }
2013
2125
  function readWorktreeInclude(repoPath) {
2014
- const path = join6(repoPath, ".worktreeinclude");
2126
+ const path = join7(repoPath, ".worktreeinclude");
2015
2127
  if (!existsSync5(path)) return [];
2016
2128
  return readFileSync4(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
2017
2129
  }
@@ -2052,9 +2164,9 @@ function copyConfiguredFiles(repoPath, worktreePath) {
2052
2164
  const patterns = resolveFilesToCopy(repoPath);
2053
2165
  const copied = [];
2054
2166
  for (const rel of patterns) {
2055
- const src = join6(repoPath, rel);
2167
+ const src = join7(repoPath, rel);
2056
2168
  if (!existsSync5(src)) continue;
2057
- const dest = join6(worktreePath, rel);
2169
+ const dest = join7(worktreePath, rel);
2058
2170
  mkdirSync3(dirname2(dest), { recursive: true });
2059
2171
  copyFileSync(src, dest);
2060
2172
  copied.push(rel);
@@ -2359,7 +2471,7 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
2359
2471
  // src/store/setup-log.ts
2360
2472
  import { createHash } from "crypto";
2361
2473
  import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
2362
- import { join as join7 } from "path";
2474
+ import { join as join8 } from "path";
2363
2475
  var EMPTY = {
2364
2476
  output: "",
2365
2477
  running: false,
@@ -2401,7 +2513,7 @@ function materialize(mem) {
2401
2513
  };
2402
2514
  }
2403
2515
  function setupLogPath(threadId) {
2404
- return join7(threadsDir(), `${threadId}.setup.log.json`);
2516
+ return join8(threadsDir(), `${threadId}.setup.log.json`);
2405
2517
  }
2406
2518
  function setupLogKeyForWorktree(worktreePath) {
2407
2519
  const norm = normalizeWorktreePath(worktreePath);
@@ -2510,7 +2622,7 @@ function finishSetupLog(threadId, exitCode, source) {
2510
2622
 
2511
2623
  // src/git/orphan-cleanup.ts
2512
2624
  import { existsSync as existsSync7, readdirSync as readdirSync2, statSync } from "fs";
2513
- import { join as join8 } from "path";
2625
+ import { join as join9 } from "path";
2514
2626
  function isSideboardWorktreePath(path) {
2515
2627
  return path.includes("/.sideboard/worktrees/") || path.includes("/sideboard/workspaces/");
2516
2628
  }
@@ -2557,9 +2669,9 @@ async function findOrphanWorktrees(repoPaths) {
2557
2669
  if (existsSync7(root)) {
2558
2670
  for (const entry of readdirSync2(root, { withFileTypes: true })) {
2559
2671
  if (!entry.isDirectory()) continue;
2560
- const path = join8(root, entry.name).replace(/\/$/, "");
2672
+ const path = join9(root, entry.name).replace(/\/$/, "");
2561
2673
  if (known.has(path) || seen.has(path)) continue;
2562
- if (!existsSync7(join8(path, ".git"))) continue;
2674
+ if (!existsSync7(join9(path, ".git"))) continue;
2563
2675
  seen.add(path);
2564
2676
  let mtimeMs = 0;
2565
2677
  try {
@@ -2773,7 +2885,7 @@ async function applyThreadIntoMain(thread, opts) {
2773
2885
 
2774
2886
  // src/git/clone-repo.ts
2775
2887
  import { existsSync as existsSync8 } from "fs";
2776
- import { basename as basename2, join as join9 } from "path";
2888
+ import { basename as basename2, join as join10 } from "path";
2777
2889
  import { execa as execa4 } from "execa";
2778
2890
  async function cloneRepoIntoSideboard(opts) {
2779
2891
  const url = opts.url.trim();
@@ -2784,7 +2896,7 @@ async function cloneRepoIntoSideboard(opts) {
2784
2896
  name = leaf || "repo";
2785
2897
  }
2786
2898
  name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
2787
- const dest = join9(sideboardReposDir(), name);
2899
+ const dest = join10(sideboardReposDir(), name);
2788
2900
  if (existsSync8(dest)) {
2789
2901
  const repoPath2 = await resolveRepoRoot(dest);
2790
2902
  const workspace2 = await ensureWorkspace(repoPath2);
@@ -2803,9 +2915,9 @@ async function cloneRepoIntoSideboard(opts) {
2803
2915
 
2804
2916
  // src/store/desktop-host.ts
2805
2917
  import { readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
2806
- import { join as join10 } from "path";
2918
+ import { join as join11 } from "path";
2807
2919
  function desktopHostPidPath() {
2808
- return join10(appDataDir(), "desktop-host.pid");
2920
+ return join11(appDataDir(), "desktop-host.pid");
2809
2921
  }
2810
2922
  function claimDesktopHost(pid = process.pid) {
2811
2923
  writeFileSync3(desktopHostPidPath(), `${pid}
@@ -2891,14 +3003,14 @@ function notifyParentOfChildHalt(child, status, send) {
2891
3003
 
2892
3004
  // src/mcp/wait-for-job.ts
2893
3005
  import {
2894
- appendFileSync,
3006
+ appendFileSync as appendFileSync2,
2895
3007
  existsSync as existsSync9,
2896
3008
  mkdirSync as mkdirSync4,
2897
3009
  readdirSync as readdirSync3,
2898
3010
  readFileSync as readFileSync7,
2899
3011
  writeFileSync as writeFileSync4
2900
3012
  } from "fs";
2901
- import { dirname as dirname3, join as join11 } from "path";
3013
+ import { dirname as dirname3, join as join12 } from "path";
2902
3014
 
2903
3015
  // src/mcp/wait-for-turn.ts
2904
3016
  var MCP_WAIT_FOR_TURN_MAX_MS = 45e3;
@@ -2970,7 +3082,7 @@ function readIntFile(file) {
2970
3082
  return Number.isInteger(n) ? n : null;
2971
3083
  }
2972
3084
  function jobDir(root, id, legacy = false) {
2973
- return join11(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
3085
+ return join12(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
2974
3086
  }
2975
3087
  function resolveJobDir(root, id) {
2976
3088
  const modern = jobDir(root, id, false);
@@ -2980,7 +3092,7 @@ function resolveJobDir(root, id) {
2980
3092
  return modern;
2981
3093
  }
2982
3094
  function listJobIdsIn(root, rel) {
2983
- const dir = join11(root, rel);
3095
+ const dir = join12(root, rel);
2984
3096
  if (!existsSync9(dir)) return [];
2985
3097
  return readdirSync3(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
2986
3098
  }
@@ -2994,7 +3106,7 @@ function listRunningDetachedJobs(worktreePath) {
2994
3106
  const running = [];
2995
3107
  for (const id of ids) {
2996
3108
  const dir = resolveJobDir(root, id);
2997
- const pid = readIntFile(join11(dir, "pid"));
3109
+ const pid = readIntFile(join12(dir, "pid"));
2998
3110
  if (jobTreeAlive(pid)) running.push(id);
2999
3111
  }
3000
3112
  return running.sort();
@@ -3007,6 +3119,7 @@ function looksLikeDeferredDonePromise(text) {
3007
3119
  return /\b(i['’]?ll|i will)\s+let you know\b/i.test(unquoted) || /\blet you know when\b/i.test(unquoted) || /\b(check back|ping me)\s+when\b/i.test(unquoted) || /\bi(?:['’]ll| will)\s+(report|update you)\s+when\b/i.test(unquoted);
3008
3120
  }
3009
3121
  function isJobContinuePrompt(text) {
3122
+ if (typeof text !== "string") return false;
3010
3123
  const t = text.trim();
3011
3124
  return t.startsWith("Detached job still running:") || t.startsWith("You ended the turn after promising to report later");
3012
3125
  }
@@ -3097,15 +3210,15 @@ function takeDelta(logFile, cursorFile) {
3097
3210
  return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
3098
3211
  }
3099
3212
  function snapshotJob(dir) {
3100
- const pid = readIntFile(join11(dir, "pid"));
3213
+ const pid = readIntFile(join12(dir, "pid"));
3101
3214
  const running = jobTreeAlive(pid);
3102
3215
  return {
3103
3216
  pid,
3104
3217
  running,
3105
- exitCode: readIntFile(join11(dir, "exit")),
3106
- log: join11(dir, "log"),
3107
- cursor: join11(dir, "present.cursor"),
3108
- progress: tailProgress(join11(dir, "log"))
3218
+ exitCode: readIntFile(join12(dir, "exit")),
3219
+ log: join12(dir, "log"),
3220
+ cursor: join12(dir, "present.cursor"),
3221
+ progress: tailProgress(join12(dir, "log"))
3109
3222
  };
3110
3223
  }
3111
3224
  function toResult(id, snap, extra) {
@@ -3193,7 +3306,7 @@ function appendJobLog(logFile, line) {
3193
3306
  mkdirSync4(dirname3(logFile), { recursive: true });
3194
3307
  const body = line.endsWith("\n") ? line : `${line}
3195
3308
  `;
3196
- appendFileSync(logFile, body);
3309
+ appendFileSync2(logFile, body);
3197
3310
  } catch {
3198
3311
  }
3199
3312
  }
@@ -3239,7 +3352,7 @@ async function stopDetachedJob(cwd, id, opts) {
3239
3352
  killProcessTree(targetPid, "SIGKILL");
3240
3353
  await sleep(100);
3241
3354
  }
3242
- const exitFile = join11(dir, "exit");
3355
+ const exitFile = join12(dir, "exit");
3243
3356
  if (!existsSync9(exitFile)) {
3244
3357
  try {
3245
3358
  writeFileSync4(exitFile, "1\n");
@@ -3905,7 +4018,7 @@ async function createThread(input, _onSetupLine) {
3905
4018
  });
3906
4019
  await requireAgent(resolved.agent);
3907
4020
  if (input.cowboy) {
3908
- const { cowboyModeEnabled } = await import("./app-settings-2TN3WLZV.js");
4021
+ const { cowboyModeEnabled } = await import("./app-settings-V2BBCX2H.js");
3909
4022
  if (!cowboyModeEnabled()) {
3910
4023
  throw new Error(
3911
4024
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -3963,7 +4076,7 @@ async function createThread(input, _onSetupLine) {
3963
4076
  let sourceIsFork = false;
3964
4077
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
3965
4078
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
3966
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-GDZLZRMY.js");
4079
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-D6773P33.js");
3967
4080
  const task = await ensureAbleTimeTask({
3968
4081
  title: title?.trim() || "Untitled work",
3969
4082
  description: input.prompt?.trim() || void 0
@@ -4065,7 +4178,7 @@ async function createThread(input, _onSetupLine) {
4065
4178
  return readThread(thread.id) ?? thread;
4066
4179
  }
4067
4180
  async function listLinearIssues(agent, repoPath) {
4068
- const { getAdapter: getAdapter2 } = await import("./agents-HETHRRZJ.js");
4181
+ const { getAdapter: getAdapter2 } = await import("./agents-YABJUV3V.js");
4069
4182
  await requireAgent(agent, { requireLinear: true });
4070
4183
  const adapter = getAdapter2(agent);
4071
4184
  if (!adapter.listLinearIssues) {
@@ -4451,19 +4564,19 @@ import {
4451
4564
  rmSync
4452
4565
  } from "fs";
4453
4566
  import { tmpdir } from "os";
4454
- import { join as join12 } from "path";
4567
+ import { join as join13 } from "path";
4455
4568
  import { createRequire } from "module";
4456
- var CONDUCTOR_APP_SUPPORT = join12(
4569
+ var CONDUCTOR_APP_SUPPORT = join13(
4457
4570
  process.env.HOME ?? "",
4458
4571
  "Library",
4459
4572
  "Application Support",
4460
4573
  "com.conductor.app"
4461
4574
  );
4462
- var CONDUCTOR_DB = join12(CONDUCTOR_APP_SUPPORT, "conductor.db");
4463
- var CURSOR_SDK_STORE = join12(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
4575
+ var CONDUCTOR_DB = join13(CONDUCTOR_APP_SUPPORT, "conductor.db");
4576
+ var CURSOR_SDK_STORE = join13(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
4464
4577
  function thisModuleFile() {
4465
4578
  const cjsFile = typeof __filename !== "undefined" ? __filename : "";
4466
- return cjsFile || process.argv[1] || join12(process.cwd(), "package.json");
4579
+ return cjsFile || process.argv[1] || join13(process.cwd(), "package.json");
4467
4580
  }
4468
4581
  function openReadonlySqlite(file) {
4469
4582
  const req = createRequire(thisModuleFile());
@@ -4491,7 +4604,7 @@ function resolveConductorCursorAgentId(workspacePath) {
4491
4604
  return null;
4492
4605
  }
4493
4606
  for (const hash of hashes) {
4494
- const agentsFile = join12(CURSOR_SDK_STORE, hash, "agents.ndjson");
4607
+ const agentsFile = join13(CURSOR_SDK_STORE, hash, "agents.ndjson");
4495
4608
  if (!existsSync12(agentsFile)) continue;
4496
4609
  let text;
4497
4610
  try {
@@ -4523,7 +4636,7 @@ async function adoptThread(input) {
4523
4636
  throw new Error(`Worktree not found: ${input.worktreePath}`);
4524
4637
  }
4525
4638
  const repoPath = await resolveRepoRoot(input.worktreePath);
4526
- const { stdout: branch } = await import("./run-CAGKZLHA.js").then(
4639
+ const { stdout: branch } = await import("./run-UEQM4JMZ.js").then(
4527
4640
  ({ git: git2 }) => git2(["rev-parse", "--abbrev-ref", "HEAD"], input.worktreePath)
4528
4641
  );
4529
4642
  const thread = createEmptyThread({
@@ -4538,9 +4651,9 @@ async function adoptThread(input) {
4538
4651
  messages: input.messages ?? []
4539
4652
  });
4540
4653
  writeThread(thread);
4541
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-R5LJCJRB.js");
4654
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-BCBBMMXB.js");
4542
4655
  await ensureWorkspace2(repoPath);
4543
- const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
4656
+ const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-L32WEBX6.js");
4544
4657
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
4545
4658
  return thread;
4546
4659
  }
@@ -4551,8 +4664,8 @@ function listConductorWorkspaces() {
4551
4664
  if (!existsSync12(CONDUCTOR_DB)) {
4552
4665
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
4553
4666
  }
4554
- const tmp = mkdtempSync(join12(tmpdir(), "sideboard-conductor-"));
4555
- const snapshot = join12(tmp, "conductor.db");
4667
+ const tmp = mkdtempSync(join13(tmpdir(), "sideboard-conductor-"));
4668
+ const snapshot = join13(tmp, "conductor.db");
4556
4669
  try {
4557
4670
  copyFileSync2(CONDUCTOR_DB, snapshot);
4558
4671
  for (const suffix of ["-wal", "-shm"]) {
@@ -4642,8 +4755,8 @@ function importConductorWorkspace(workspaceId) {
4642
4755
  if (!existsSync12(CONDUCTOR_DB)) {
4643
4756
  throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
4644
4757
  }
4645
- const tmp = mkdtempSync(join12(tmpdir(), "sideboard-conductor-"));
4646
- const snapshot = join12(tmp, "conductor.db");
4758
+ const tmp = mkdtempSync(join13(tmpdir(), "sideboard-conductor-"));
4759
+ const snapshot = join13(tmp, "conductor.db");
4647
4760
  try {
4648
4761
  copyFileSync2(CONDUCTOR_DB, snapshot);
4649
4762
  for (const suffix of ["-wal", "-shm"]) {
@@ -5034,7 +5147,7 @@ function stackAgentDefaultsFrom(input) {
5034
5147
 
5035
5148
  // src/diff/diff.ts
5036
5149
  import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
5037
- import { dirname as dirname4, join as join13 } from "path";
5150
+ import { dirname as dirname4, join as join14 } from "path";
5038
5151
  async function inspectGitWorktree(worktreePath) {
5039
5152
  if (!worktreePath || !existsSync14(worktreePath)) return "missing_worktree";
5040
5153
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
@@ -5180,7 +5293,7 @@ new file mode 100644
5180
5293
  };
5181
5294
  }
5182
5295
  async function untrackedPatch(worktreePath, path, maxHunk) {
5183
- const abs = join13(worktreePath, path);
5296
+ const abs = join14(worktreePath, path);
5184
5297
  try {
5185
5298
  const st = statSync2(abs);
5186
5299
  if (st.isFile() && st.size > maxHunk) {
@@ -5650,6 +5763,15 @@ async function getDiff(worktreePath, repoPath, opts) {
5650
5763
  mergeBase: needsMergeBase ? mergeBase : null
5651
5764
  };
5652
5765
  }
5766
+ function statWorktreePath(worktreePath, relativePath) {
5767
+ assertSafeRelativePath(relativePath);
5768
+ const abs = join14(worktreePath, relativePath);
5769
+ if (!existsSync14(abs)) return "missing";
5770
+ const st = statSync2(abs);
5771
+ if (st.isDirectory()) return "dir";
5772
+ if (st.isFile()) return "file";
5773
+ return "missing";
5774
+ }
5653
5775
  async function listWorktreeFiles(worktreePath, opts) {
5654
5776
  const maxFiles = opts?.maxFiles ?? 5e3;
5655
5777
  const tracked = await git(["ls-files", "-z"], worktreePath, { reject: false });
@@ -5685,7 +5807,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
5685
5807
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
5686
5808
  assertSafeRelativePath(relativePath);
5687
5809
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
5688
- const abs = join13(worktreePath, relativePath);
5810
+ const abs = join14(worktreePath, relativePath);
5689
5811
  const st = statSync2(abs);
5690
5812
  if (!st.isFile()) {
5691
5813
  throw new Error(`Not a file: ${relativePath}`);
@@ -5705,7 +5827,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
5705
5827
  function readWorktreeFile(worktreePath, relativePath, opts) {
5706
5828
  assertSafeRelativePath(relativePath);
5707
5829
  const maxBytes = opts?.maxBytes ?? 2e5;
5708
- const abs = join13(worktreePath, relativePath);
5830
+ const abs = join14(worktreePath, relativePath);
5709
5831
  const st = statSync2(abs);
5710
5832
  if (!st.isFile()) {
5711
5833
  throw new Error(`Not a file: ${relativePath}`);
@@ -5753,7 +5875,7 @@ function assertSafeRelativePath(relativePath) {
5753
5875
  }
5754
5876
  function writeWorktreeFile(worktreePath, relativePath, content) {
5755
5877
  assertSafeRelativePath(relativePath);
5756
- const abs = join13(worktreePath, relativePath);
5878
+ const abs = join14(worktreePath, relativePath);
5757
5879
  mkdirSync5(dirname4(abs), { recursive: true });
5758
5880
  writeFileSync6(abs, content, "utf8");
5759
5881
  return { path: relativePath };
@@ -5947,7 +6069,7 @@ async function confirmLand(thread, opts) {
5947
6069
  if (preview.dirty) {
5948
6070
  committed = await commitAll(thread.worktreePath, meta.commitMessage);
5949
6071
  }
5950
- const { git: git2 } = await import("./run-CAGKZLHA.js");
6072
+ const { git: git2 } = await import("./run-UEQM4JMZ.js");
5951
6073
  const { stdout: headOut } = await git2(
5952
6074
  ["rev-parse", "--abbrev-ref", "HEAD"],
5953
6075
  thread.worktreePath,
@@ -5979,7 +6101,7 @@ async function confirmLand(thread, opts) {
5979
6101
  // src/skills/discover.ts
5980
6102
  import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
5981
6103
  import { homedir } from "os";
5982
- import { join as join14 } from "path";
6104
+ import { join as join15 } from "path";
5983
6105
 
5984
6106
  // src/skills/bundled/long-running.ts
5985
6107
  var LONG_RUNNING_SKILL_COMMAND = "long-running";
@@ -6144,7 +6266,7 @@ function scanSkillsDir(dir, source, out) {
6144
6266
  }
6145
6267
  for (const entry of entries) {
6146
6268
  if (entry.startsWith(".")) continue;
6147
- const skillMd = join14(dir, entry, "SKILL.md");
6269
+ const skillMd = join15(dir, entry, "SKILL.md");
6148
6270
  if (!existsSync15(skillMd)) continue;
6149
6271
  try {
6150
6272
  if (!statSync3(skillMd).isFile()) continue;
@@ -6166,12 +6288,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
6166
6288
  return;
6167
6289
  }
6168
6290
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
6169
- const skill = readSkill(join14(dir, "SKILL.md"), "cli");
6291
+ const skill = readSkill(join15(dir, "SKILL.md"), "cli");
6170
6292
  if (skill) out.push(skill);
6171
6293
  }
6172
6294
  for (const entry of entries) {
6173
6295
  if (entry === "node_modules" || entry === ".git") continue;
6174
- const full = join14(dir, entry);
6296
+ const full = join15(dir, entry);
6175
6297
  try {
6176
6298
  if (!statSync3(full).isDirectory()) continue;
6177
6299
  } catch {
@@ -6191,17 +6313,17 @@ function discoverSkills(worktreePath) {
6191
6313
  const home = homedir();
6192
6314
  const collected = [];
6193
6315
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
6194
- scanSkillsDir(join14(worktreePath, rel), "workspace", collected);
6316
+ scanSkillsDir(join15(worktreePath, rel), "workspace", collected);
6195
6317
  }
6196
6318
  for (const abs of [
6197
- join14(home, ".claude/skills"),
6198
- join14(home, ".cursor/skills"),
6199
- join14(home, ".sideboard/skills"),
6200
- join14(home, ".brightsy/skills")
6319
+ join15(home, ".claude/skills"),
6320
+ join15(home, ".cursor/skills"),
6321
+ join15(home, ".sideboard/skills"),
6322
+ join15(home, ".brightsy/skills")
6201
6323
  ]) {
6202
6324
  scanSkillsDir(abs, "user", collected);
6203
6325
  }
6204
- scanClaudePluginSkills(join14(home, ".claude/plugins"), collected);
6326
+ scanClaudePluginSkills(join15(home, ".claude/plugins"), collected);
6205
6327
  collected.push(...bundledSkills());
6206
6328
  const rank = {
6207
6329
  workspace: 0,
@@ -6373,16 +6495,28 @@ function shiftQueuedItem(queue, queueAttachments) {
6373
6495
 
6374
6496
  // src/agents/instructions.ts
6375
6497
  import { existsSync as existsSync17 } from "fs";
6376
- import { join as join16 } from "path";
6498
+ import { join as join17 } from "path";
6377
6499
 
6378
6500
  // src/skills/detached-job-path.ts
6379
6501
  import { existsSync as existsSync16 } from "fs";
6380
- import { dirname as dirname5, join as join15 } from "path";
6502
+ import { dirname as dirname5, join as join16 } from "path";
6381
6503
  import { fileURLToPath } from "url";
6382
6504
  var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
6505
+ function compiledModuleDir() {
6506
+ const cjsDir = typeof __dirname !== "undefined" ? __dirname : "";
6507
+ if (cjsDir) return cjsDir;
6508
+ try {
6509
+ const url = import.meta.url;
6510
+ if (typeof url === "string" && url.length > 0) {
6511
+ return dirname5(fileURLToPath(url));
6512
+ }
6513
+ } catch {
6514
+ }
6515
+ return null;
6516
+ }
6383
6517
  function detachedJobScriptIn(dir) {
6384
6518
  for (const name of DETACHED_JOB_FILENAMES) {
6385
- const script = join15(dir, "scripts", name);
6519
+ const script = join16(dir, "scripts", name);
6386
6520
  if (existsSync16(script)) return script;
6387
6521
  }
6388
6522
  return null;
@@ -6395,7 +6529,8 @@ function packagedDetachedJobPath() {
6395
6529
  function resolveDetachedJobScript() {
6396
6530
  const packaged = packagedDetachedJobPath();
6397
6531
  if (packaged) return packaged;
6398
- let dir = dirname5(fileURLToPath(import.meta.url));
6532
+ let dir = compiledModuleDir();
6533
+ if (!dir) return null;
6399
6534
  for (let i = 0; i < 8; i++) {
6400
6535
  const candidate = detachedJobScriptIn(dir);
6401
6536
  if (candidate) return candidate;
@@ -6588,9 +6723,9 @@ function formatPrGateDirective() {
6588
6723
  }
6589
6724
  function formatProcessGuideDirective(opts) {
6590
6725
  const worktree = opts?.worktreePath?.trim();
6591
- const hasGraphSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/graph-engineering/SKILL.md"));
6592
- const hasReviewSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/review/SKILL.md"));
6593
- const hasInstallSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/worktree-install/SKILL.md"));
6726
+ const hasGraphSkill = !!worktree && existsSync17(join17(worktree, ".claude/skills/graph-engineering/SKILL.md"));
6727
+ const hasReviewSkill = !!worktree && existsSync17(join17(worktree, ".claude/skills/review/SKILL.md"));
6728
+ const hasInstallSkill = !!worktree && existsSync17(join17(worktree, ".claude/skills/worktree-install/SKILL.md"));
6594
6729
  return [
6595
6730
  "Process guides (recurring work only):",
6596
6731
  hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
@@ -6953,7 +7088,7 @@ async function syncThreadBranchFromGit(threadId) {
6953
7088
  // src/store/schedules.ts
6954
7089
  import { randomUUID as randomUUID4 } from "crypto";
6955
7090
  import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
6956
- import { join as join17 } from "path";
7091
+ import { join as join18 } from "path";
6957
7092
  import { Cron } from "croner";
6958
7093
  var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
6959
7094
  var UNIT_MS = {
@@ -6963,7 +7098,7 @@ var UNIT_MS = {
6963
7098
  d: 864e5
6964
7099
  };
6965
7100
  function schedulesPath() {
6966
- return join17(appDataDir(), "schedules.json");
7101
+ return join18(appDataDir(), "schedules.json");
6967
7102
  }
6968
7103
  function parseDurationMs(every) {
6969
7104
  const m = every.trim().match(DURATION_RE);
@@ -7197,7 +7332,7 @@ function formatScheduledPrompt(name, prompt) {
7197
7332
  ${prompt}`;
7198
7333
  }
7199
7334
  async function defaultDeps() {
7200
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-WVZPTHBV.js");
7335
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-HKW3VLGX.js");
7201
7336
  const orch = getOrchestrator2();
7202
7337
  return {
7203
7338
  findThread: (id) => findThreadByRef(id),
@@ -7499,7 +7634,7 @@ var Orchestrator = class {
7499
7634
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
7500
7635
  });
7501
7636
  }
7502
- const { autoCleanupOrphansEnabled } = await import("./app-settings-2TN3WLZV.js");
7637
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-V2BBCX2H.js");
7503
7638
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
7504
7639
  await cleanupOrphanWorktrees({ repoPaths });
7505
7640
  }
@@ -7531,7 +7666,7 @@ var Orchestrator = class {
7531
7666
  }
7532
7667
  if (thread.queue.length > 0) {
7533
7668
  this.haltDrain.delete(thread.id);
7534
- void this.drainQueue(thread.id);
7669
+ this.armDrain(thread.id);
7535
7670
  }
7536
7671
  }
7537
7672
  }
@@ -7786,7 +7921,7 @@ var Orchestrator = class {
7786
7921
  }
7787
7922
  await setup;
7788
7923
  if (skipSetup) return;
7789
- const { autoRunAfterSetupEnabled } = await import("./app-settings-2TN3WLZV.js");
7924
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-V2BBCX2H.js");
7790
7925
  if (autoRunAfterSetupEnabled()) {
7791
7926
  try {
7792
7927
  await this.startDev(threadId);
@@ -7867,7 +8002,7 @@ var Orchestrator = class {
7867
8002
  this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
7868
8003
  }
7869
8004
  if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
7870
- void this.drainQueue(thread.id);
8005
+ this.armDrain(thread.id);
7871
8006
  }
7872
8007
  return this.requireThread(thread.id);
7873
8008
  });
@@ -7947,9 +8082,15 @@ var Orchestrator = class {
7947
8082
  if (inFlight || foreignLive) {
7948
8083
  this.stop(thread.id, { clearQueue: false, continueQueue: true });
7949
8084
  }
7950
- void this.drainQueue(thread.id);
8085
+ this.armDrain(thread.id);
7951
8086
  return this.requireThread(thread.id);
7952
8087
  }
8088
+ armDrain(threadId) {
8089
+ void this.drainQueue(threadId).catch((err) => {
8090
+ const detail = err instanceof Error ? err.message : String(err);
8091
+ console.error(`[sideboard] drainQueue ${threadId}: ${detail}`);
8092
+ });
8093
+ }
7953
8094
  async drainQueue(threadId) {
7954
8095
  if (this.draining.has(threadId)) return;
7955
8096
  this.draining.add(threadId);
@@ -8021,196 +8162,205 @@ var Orchestrator = class {
8021
8162
  this.emit({ type: "status_changed", threadId, status: "running" });
8022
8163
  this.emit({ type: "turn_started", threadId, prompt });
8023
8164
  try {
8024
- const baseline = await captureTurnBaseline(thread.worktreePath);
8025
- if (baseline) this.turnBaselines.set(threadId, baseline);
8026
- } catch {
8027
- }
8028
- try {
8029
- const compact = await maybeCompactContext(thread);
8030
- if (compact.didCompact) {
8031
- thread = updateThread(threadId, {
8032
- messages: compact.thread.messages,
8033
- sessionId: compact.thread.sessionId
8034
- });
8035
- this.emit({
8036
- type: "context_compacted",
8037
- threadId,
8038
- olderCount: compact.olderCount ?? 0,
8039
- method: compact.method ?? "extractive"
8040
- });
8165
+ try {
8166
+ const baseline = await captureTurnBaseline(thread.worktreePath);
8167
+ if (baseline) this.turnBaselines.set(threadId, baseline);
8168
+ } catch {
8041
8169
  }
8042
- } catch (err) {
8043
- const message = err instanceof Error ? err.message : String(err);
8044
- this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
8045
- thread = this.requireThread(threadId);
8046
- }
8047
- const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
8048
- const parked = takePendingTurnAttachments(thread);
8049
- const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
8050
- appendMessage(threadId, {
8051
- role: "user",
8052
- text: prompt,
8053
- ...sentAttachments ? { attachments: sentAttachments } : {},
8054
- ...autoContinue ? { origin: "continue" } : {},
8055
- ts: (/* @__PURE__ */ new Date()).toISOString()
8056
- });
8057
- thread = this.requireThread(threadId);
8058
- const gitPrompt = expandCanonicalGitRequest(prompt);
8059
- const { agentPrompt: expandedPrompt } = expandComposerPrompt(
8060
- thread.worktreePath,
8061
- gitPrompt,
8062
- {
8063
- attachments: autoContinue ? [] : sentAttachments ?? []
8170
+ try {
8171
+ const compact = await maybeCompactContext(thread);
8172
+ if (compact.didCompact) {
8173
+ thread = updateThread(threadId, {
8174
+ messages: compact.thread.messages,
8175
+ sessionId: compact.thread.sessionId
8176
+ });
8177
+ this.emit({
8178
+ type: "context_compacted",
8179
+ threadId,
8180
+ olderCount: compact.olderCount ?? 0,
8181
+ method: compact.method ?? "extractive"
8182
+ });
8183
+ }
8184
+ } catch (err) {
8185
+ const message = err instanceof Error ? err.message : String(err);
8186
+ this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
8187
+ thread = this.requireThread(threadId);
8064
8188
  }
8065
- );
8066
- const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
8067
- expandedPrompt.trim()
8068
- );
8069
- const orchestrationReminder = isOrchestratorThread(thread) ? [
8070
- coordinatorTurnReminder({
8071
- parentId: threadId,
8072
- goal: thread.sourceRef || thread.title
8073
- }),
8074
- slackInbound ? [
8075
- "This turn is a Slack DM or @mention. Your reply is posted back in Slack \u2014 keep it concise. Sideboard signs it with this Mac's destination name; do not prefix the name yourself.",
8076
- SLACK_REPLY_FORMATTING
8077
- ].join("\n") : null
8078
- ].filter(Boolean).join("\n") : null;
8079
- const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
8080
- const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder() : null;
8081
- const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
8082
- const optionalServicesReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatOptionalServicesReminder(loadAppSettings().integrations) : null;
8083
- const issueTicket = issueTicketFromThread(thread, resolveEffectiveIssueSource());
8084
- const issueToolsReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatIssueToolsReminder({
8085
- linear: isLinearConnected(),
8086
- abletime: isAbleTimeConnected(),
8087
- github: true,
8088
- ticketId: issueTicket?.id,
8089
- ticketProvider: issueTicket?.provider
8090
- }) : null;
8091
- const viewerContextReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatViewerContextReminder() : null;
8092
- const reviewWriteGateReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && isReviewWriteGatedThread(
8093
- thread,
8094
- thread.worktreePath ? threadsSharingWorktree(thread.worktreePath) : []
8095
- ) ? formatReviewWriteGateReminder() : null;
8096
- const slackReplyContext = formatSlackRepliesForTurn(
8097
- pendingSlackExternalReplies(thread.messages)
8098
- );
8099
- const turnReminders = [
8100
- worktreeReminder,
8101
- optionalServicesReminder,
8102
- issueToolsReminder,
8103
- reviewWriteGateReminder,
8104
- viewerContextReminder,
8105
- artifactReminder,
8106
- longRunningReminder
8107
- ].filter(Boolean).join("\n\n") || void 0;
8108
- const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(prompt) ? formatPrGateDirective() : null;
8109
- const agentPrompt = [
8110
- thread.planMode ? PLAN_MODE_INSTRUCTION : null,
8111
- orchestrationReminder,
8112
- prGateDirective,
8113
- slackReplyContext,
8114
- expandedPrompt
8115
- ].filter(Boolean).join("\n\n");
8116
- if (!autoContinue && sentAttachments) {
8117
- updateThread(threadId, { pendingTurnAttachments: [] });
8118
- }
8119
- const adapter = getAdapter(thread.agent);
8120
- const resolved = await adapter.resolveSessionId(thread.worktreePath, thread.sessionId);
8121
- if (resolved && resolved !== thread.sessionId) {
8122
- updateThread(threadId, { sessionId: resolved });
8123
- }
8124
- const fresh = this.requireThread(threadId);
8125
- if (!fresh.worktreePath?.trim()) {
8126
- throw new Error(
8127
- `Thread ${threadId} has no worktreePath \u2014 refusing to start an agent outside an isolated worktree`
8189
+ const promptText = typeof prompt === "string" ? prompt : "";
8190
+ const autoContinue = isJobContinuePrompt(promptText) || promptText.startsWith("The previous agent process ended before it finished.");
8191
+ const parked = takePendingTurnAttachments(thread);
8192
+ const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
8193
+ appendMessage(threadId, {
8194
+ role: "user",
8195
+ text: promptText,
8196
+ ...sentAttachments ? { attachments: sentAttachments } : {},
8197
+ ...autoContinue ? { origin: "continue" } : {},
8198
+ ts: (/* @__PURE__ */ new Date()).toISOString()
8199
+ });
8200
+ traceTurn("runTurn.afterUserMessage", {
8201
+ threadId,
8202
+ agent: thread.agent,
8203
+ orch: isOrchestratorThread(thread)
8204
+ });
8205
+ thread = this.requireThread(threadId);
8206
+ const gitPrompt = expandCanonicalGitRequest(promptText);
8207
+ const { agentPrompt: expandedPrompt } = expandComposerPrompt(
8208
+ thread.worktreePath,
8209
+ gitPrompt,
8210
+ {
8211
+ attachments: autoContinue ? [] : sentAttachments ?? []
8212
+ }
8128
8213
  );
8129
- }
8130
- const isBrightsy = fresh.agent === "brightsy";
8131
- const isOrchestration = isOrchestratorThread(fresh);
8132
- const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-2TN3WLZV.js");
8133
- const gitAuthMode = getGithubGitAuthMode();
8134
- const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
8135
- githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
8136
- () => null
8137
- ),
8138
- gitAuthMode
8139
- });
8140
- const artifactDirective = isBrightsy ? null : formatArtifactDirective();
8141
- const longRunningDirective = isBrightsy || isOrchestration ? null : formatLongRunningDirective();
8142
- const optionalServicesDirective = isBrightsy || isOrchestration ? null : formatOptionalServicesDirective(loadAppSettings().integrations);
8143
- const freshIssueTicket = issueTicketFromThread(fresh, resolveEffectiveIssueSource());
8144
- const issueToolsDirective = isBrightsy || isOrchestration ? null : formatIssueToolsDirective({
8145
- linear: isLinearConnected(),
8146
- abletime: isAbleTimeConnected(),
8147
- github: true,
8148
- ticketId: freshIssueTicket?.id,
8149
- ticketProvider: freshIssueTicket?.provider
8150
- });
8151
- const reviewWriteGateDirective = isBrightsy || isOrchestration || !isReviewWriteGatedThread(
8152
- fresh,
8153
- fresh.worktreePath ? threadsSharingWorktree(fresh.worktreePath) : []
8154
- ) ? null : formatReviewWriteGateDirective();
8155
- let viewerContextDirective = null;
8156
- if (!isBrightsy && !isOrchestration) {
8157
- try {
8158
- viewerContextDirective = formatViewerContextDirective(
8159
- resolveViewerProfileForRepo(fresh.repoPath || fresh.worktreePath)
8160
- );
8161
- } catch {
8162
- viewerContextDirective = formatViewerContextDirective(
8163
- resolveViewerProfileForRepo()
8214
+ const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
8215
+ expandedPrompt.trim()
8216
+ );
8217
+ const orchestrationReminder = isOrchestratorThread(thread) ? [
8218
+ coordinatorTurnReminder({
8219
+ parentId: threadId,
8220
+ goal: thread.sourceRef || thread.title
8221
+ }),
8222
+ slackInbound ? [
8223
+ "This turn is a Slack DM or @mention. Your reply is posted back in Slack \u2014 keep it concise. Sideboard signs it with this Mac's destination name; do not prefix the name yourself.",
8224
+ SLACK_REPLY_FORMATTING
8225
+ ].join("\n") : null
8226
+ ].filter(Boolean).join("\n") : null;
8227
+ const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
8228
+ const longRunningReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatLongRunningReminder() : null;
8229
+ const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
8230
+ const optionalServicesReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatOptionalServicesReminder(loadAppSettings().integrations) : null;
8231
+ const issueTicket = issueTicketFromThread(thread, resolveEffectiveIssueSource());
8232
+ const issueToolsReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatIssueToolsReminder({
8233
+ linear: isLinearConnected(),
8234
+ abletime: isAbleTimeConnected(),
8235
+ github: true,
8236
+ ticketId: issueTicket?.id,
8237
+ ticketProvider: issueTicket?.provider
8238
+ }) : null;
8239
+ const viewerContextReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatViewerContextReminder() : null;
8240
+ const reviewWriteGateReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && isReviewWriteGatedThread(
8241
+ thread,
8242
+ thread.worktreePath ? threadsSharingWorktree(thread.worktreePath) : []
8243
+ ) ? formatReviewWriteGateReminder() : null;
8244
+ const slackReplyContext = formatSlackRepliesForTurn(
8245
+ pendingSlackExternalReplies(thread.messages)
8246
+ );
8247
+ const turnReminders = [
8248
+ worktreeReminder,
8249
+ optionalServicesReminder,
8250
+ issueToolsReminder,
8251
+ reviewWriteGateReminder,
8252
+ viewerContextReminder,
8253
+ artifactReminder,
8254
+ longRunningReminder
8255
+ ].filter(Boolean).join("\n\n") || void 0;
8256
+ const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(promptText) ? formatPrGateDirective() : null;
8257
+ const agentPrompt = [
8258
+ thread.planMode ? PLAN_MODE_INSTRUCTION : null,
8259
+ orchestrationReminder,
8260
+ prGateDirective,
8261
+ slackReplyContext,
8262
+ expandedPrompt
8263
+ ].filter(Boolean).join("\n\n");
8264
+ if (!autoContinue && sentAttachments) {
8265
+ updateThread(threadId, { pendingTurnAttachments: [] });
8266
+ }
8267
+ const adapter = getAdapter(thread.agent);
8268
+ const resolved = await adapter.resolveSessionId(thread.worktreePath, thread.sessionId);
8269
+ if (resolved && resolved !== thread.sessionId) {
8270
+ updateThread(threadId, { sessionId: resolved });
8271
+ }
8272
+ const fresh = this.requireThread(threadId);
8273
+ if (!fresh.worktreePath?.trim()) {
8274
+ throw new Error(
8275
+ `Thread ${threadId} has no worktreePath \u2014 refusing to start an agent outside an isolated worktree`
8164
8276
  );
8165
8277
  }
8166
- }
8167
- const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
8168
- let renameBranchDirective = null;
8169
- if (!isBrightsy && !isOrchestration && autoRenameBranchEnabled()) {
8170
- const { resolveGitBranchPrefix } = await import("./branch-prefix-N3KTCRCE.js");
8171
- renameBranchDirective = formatRenameBranchDirective(fresh, {
8172
- customPrompt: settings?.prompts?.renameBranch,
8173
- branchPrefix: resolveGitBranchPrefix({
8174
- setting: gitBranchPrefixSetting()
8175
- })
8278
+ const isBrightsy = fresh.agent === "brightsy";
8279
+ const isOrchestration = isOrchestratorThread(fresh);
8280
+ const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-V2BBCX2H.js");
8281
+ const gitAuthMode = getGithubGitAuthMode();
8282
+ const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
8283
+ githubSlug: await withTimeout(
8284
+ resolveGithubRepoSlug(fresh.worktreePath),
8285
+ 8e3,
8286
+ "resolveGithubRepoSlug"
8287
+ ).catch(() => null),
8288
+ gitAuthMode
8176
8289
  });
8177
- }
8178
- let seed = null;
8179
- if (!fresh.sessionId) {
8180
- const prior = fresh.messages.slice(0, -1);
8181
- seed = isBrightsy ? buildBrightsySessionSeed(prior) : buildSessionSeed(prior);
8182
- }
8183
- let coordinatorDirective = null;
8184
- if (isOrchestration) {
8185
- if (isGlobalThread(fresh)) {
8186
- ensureGlobalCoordinatorCwd({ orchestratorThreadId: fresh.id });
8290
+ const artifactDirective = isBrightsy ? null : formatArtifactDirective();
8291
+ const longRunningDirective = isBrightsy || isOrchestration ? null : formatLongRunningDirective();
8292
+ const optionalServicesDirective = isBrightsy || isOrchestration ? null : formatOptionalServicesDirective(loadAppSettings().integrations);
8293
+ const freshIssueTicket = issueTicketFromThread(fresh, resolveEffectiveIssueSource());
8294
+ const issueToolsDirective = isBrightsy || isOrchestration ? null : formatIssueToolsDirective({
8295
+ linear: isLinearConnected(),
8296
+ abletime: isAbleTimeConnected(),
8297
+ github: true,
8298
+ ticketId: freshIssueTicket?.id,
8299
+ ticketProvider: freshIssueTicket?.provider
8300
+ });
8301
+ const reviewWriteGateDirective = isBrightsy || isOrchestration || !isReviewWriteGatedThread(
8302
+ fresh,
8303
+ fresh.worktreePath ? threadsSharingWorktree(fresh.worktreePath) : []
8304
+ ) ? null : formatReviewWriteGateDirective();
8305
+ let viewerContextDirective = null;
8306
+ if (!isBrightsy && !isOrchestration) {
8307
+ try {
8308
+ viewerContextDirective = formatViewerContextDirective(
8309
+ resolveViewerProfileForRepo(fresh.repoPath || fresh.worktreePath)
8310
+ );
8311
+ } catch {
8312
+ viewerContextDirective = formatViewerContextDirective(
8313
+ resolveViewerProfileForRepo()
8314
+ );
8315
+ }
8187
8316
  }
8188
- if (!fresh.sessionId) {
8189
- const inventory = await enrichWorkspacesWithGithub(this.listWorkspaces());
8190
- coordinatorDirective = coordinatorSystemPrompt({
8191
- goal: fresh.sourceRef || fresh.title || "Orchestration",
8192
- parentId: fresh.id,
8193
- workspaces: inventory,
8194
- audience: /^(Slack DM|Slack @mention)(?:\n|$)/.test(
8195
- expandedPrompt.trim()
8196
- ) ? "slack" : "desktop"
8317
+ const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
8318
+ let renameBranchDirective = null;
8319
+ if (!isBrightsy && !isOrchestration && autoRenameBranchEnabled()) {
8320
+ const { resolveGitBranchPrefix } = await import("./branch-prefix-N3KTCRCE.js");
8321
+ renameBranchDirective = formatRenameBranchDirective(fresh, {
8322
+ customPrompt: settings?.prompts?.renameBranch,
8323
+ branchPrefix: resolveGitBranchPrefix({
8324
+ setting: gitBranchPrefixSetting()
8325
+ })
8197
8326
  });
8198
8327
  }
8199
- }
8200
- const cachedPrefix = fresh.sessionId ? "" : [
8201
- coordinatorDirective,
8202
- worktreeDirective,
8203
- optionalServicesDirective,
8204
- issueToolsDirective,
8205
- reviewWriteGateDirective,
8206
- viewerContextDirective,
8207
- artifactDirective,
8208
- longRunningDirective,
8209
- renameBranchDirective,
8210
- seed
8211
- ].filter(Boolean).join("\n\n---\n\n");
8212
- try {
8328
+ let seed = null;
8329
+ if (!fresh.sessionId) {
8330
+ const prior = fresh.messages.slice(0, -1);
8331
+ seed = isBrightsy ? buildBrightsySessionSeed(prior) : buildSessionSeed(prior);
8332
+ }
8333
+ let coordinatorDirective = null;
8334
+ if (isOrchestration) {
8335
+ if (isGlobalThread(fresh)) {
8336
+ ensureGlobalCoordinatorCwd({ orchestratorThreadId: fresh.id });
8337
+ }
8338
+ if (!fresh.sessionId) {
8339
+ const inventory = await enrichWorkspacesWithGithub(this.listWorkspaces());
8340
+ coordinatorDirective = coordinatorSystemPrompt({
8341
+ goal: fresh.sourceRef || fresh.title || "Orchestration",
8342
+ parentId: fresh.id,
8343
+ workspaces: inventory,
8344
+ audience: /^(Slack DM|Slack @mention)(?:\n|$)/.test(
8345
+ expandedPrompt.trim()
8346
+ ) ? "slack" : "desktop"
8347
+ });
8348
+ }
8349
+ }
8350
+ const cachedPrefix = fresh.sessionId ? "" : [
8351
+ coordinatorDirective,
8352
+ worktreeDirective,
8353
+ optionalServicesDirective,
8354
+ issueToolsDirective,
8355
+ reviewWriteGateDirective,
8356
+ viewerContextDirective,
8357
+ artifactDirective,
8358
+ longRunningDirective,
8359
+ renameBranchDirective,
8360
+ seed
8361
+ ].filter(Boolean).join("\n\n---\n\n");
8213
8362
  const stderrTail = [];
8363
+ traceTurn("runTurn.beforeSpawn", { threadId, agent: fresh.agent });
8214
8364
  const handle = await spawnAgentTurn(
8215
8365
  fresh,
8216
8366
  {
@@ -9010,6 +9160,18 @@ var Orchestrator = class {
9010
9160
  const thread = this.requireThread(threadRef);
9011
9161
  return listWorktreeFiles(thread.worktreePath);
9012
9162
  }
9163
+ async statPath(threadRef, relativePath) {
9164
+ const thread = this.requireThread(threadRef);
9165
+ if (relativePath.includes("..") || relativePath.startsWith("/")) {
9166
+ return "missing";
9167
+ }
9168
+ if (!relativePath || relativePath === ".") return "dir";
9169
+ try {
9170
+ return statWorktreePath(thread.worktreePath, relativePath);
9171
+ } catch {
9172
+ return "missing";
9173
+ }
9174
+ }
9013
9175
  async readFile(threadRef, relativePath) {
9014
9176
  const thread = this.requireThread(threadRef);
9015
9177
  if (relativePath.includes("..") || relativePath.startsWith("/")) {
@@ -9165,7 +9327,7 @@ var Orchestrator = class {
9165
9327
  if (!titled.userSetTitle && meta.title && titled.title !== meta.title) {
9166
9328
  updateThread(thread.id, { title: meta.title });
9167
9329
  }
9168
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-2TN3WLZV.js");
9330
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-V2BBCX2H.js");
9169
9331
  const latest = this.requireThread(thread.id);
9170
9332
  if (!shouldAutoArchiveOnPrMerge({
9171
9333
  previousPrState: prevState || null,
@@ -9444,7 +9606,7 @@ var Orchestrator = class {
9444
9606
  this.enforceHistoryRetention();
9445
9607
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
9446
9608
  try {
9447
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-R5LJCJRB.js");
9609
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-BCBBMMXB.js");
9448
9610
  await ensureWorkspace2(thread.repoPath);
9449
9611
  } catch {
9450
9612
  }
@@ -9471,7 +9633,7 @@ var Orchestrator = class {
9471
9633
  await runArchiveScript(thread.repoPath, thread.worktreePath);
9472
9634
  } catch {
9473
9635
  }
9474
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-2TN3WLZV.js");
9636
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-V2BBCX2H.js");
9475
9637
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
9476
9638
  await removeWorktree(thread.repoPath, thread.worktreePath, {
9477
9639
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -9498,13 +9660,13 @@ var Orchestrator = class {
9498
9660
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
9499
9661
  );
9500
9662
  }
9501
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-MDMTCAHX.js");
9663
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-7V67XTEO.js");
9502
9664
  const slug = thread.worktreePath.split("/").pop();
9503
9665
  const dest = thread.worktreePath;
9504
9666
  await withRepoGitLock(thread.repoPath, async () => {
9505
9667
  await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
9506
9668
  });
9507
- const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
9669
+ const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-L32WEBX6.js");
9508
9670
  await ensureWorktreeSideboardIgnored2(dest);
9509
9671
  void createThreadWorktree2;
9510
9672
  void slug;
@@ -9608,7 +9770,7 @@ async function startOrchestration(opts) {
9608
9770
  sourceRef: "default",
9609
9771
  ...createOpts
9610
9772
  }).catch(async () => {
9611
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-MDMTCAHX.js");
9773
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-7V67XTEO.js");
9612
9774
  const repo = await resolveRepoRoot2(repoPath);
9613
9775
  const def = await resolveDefaultBranch2(repo);
9614
9776
  return orch.createThread({
@@ -9820,6 +9982,7 @@ export {
9820
9982
  captureTurnBaseline,
9821
9983
  listBranchCommits,
9822
9984
  getDiff,
9985
+ statWorktreePath,
9823
9986
  listWorktreeFiles,
9824
9987
  readWorktreeFileForUpload,
9825
9988
  readWorktreeFile,