@sideboard-ai/core 0.1.149 → 0.1.151

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 (60) hide show
  1. package/dist/{abletime-QEVAE67D.js → abletime-223A3LY6.js} +2 -2
  2. package/dist/{abletime-DI55AJX3.js → abletime-CLC5UJC2.js} +2 -2
  3. package/dist/agents/cursor-runner.cjs +40 -35
  4. package/dist/agents/cursor-runner.js +2 -2
  5. package/dist/{agents-V4MTDWXS.js → agents-JAOMXDXN.js} +10 -9
  6. package/dist/{agents-HSVQ2Z6Y.js → agents-U2JCFXW4.js} +10 -9
  7. package/dist/{app-settings-WJDCJFSY.js → app-settings-3CHCNIMD.js} +5 -1
  8. package/dist/{app-settings-ZCN632OJ.js → app-settings-J3JBCUOT.js} +5 -1
  9. package/dist/{chunk-N5PM7HGQ.js → chunk-2SDMENAL.js} +1 -1
  10. package/dist/{chunk-JTPDWTWJ.js → chunk-3JBMACYX.js} +137 -114
  11. package/dist/{chunk-I77RYPOH.js → chunk-4XNSGDXE.js} +12 -0
  12. package/dist/{chunk-JDYKQ6OI.js → chunk-6H4TJ5TA.js} +136 -75
  13. package/dist/{chunk-EGDRPA4B.js → chunk-77MP647F.js} +6 -6
  14. package/dist/{chunk-KBWND62T.js → chunk-7F4XE6UG.js} +5 -5
  15. package/dist/{chunk-R4JP32P5.js → chunk-ADCEGG4A.js} +4 -4
  16. package/dist/{chunk-BOD5V52W.js → chunk-B7XK37WZ.js} +1 -1
  17. package/dist/{chunk-BGQBELGJ.js → chunk-CZD4NRDZ.js} +12 -0
  18. package/dist/{chunk-KPIYENTF.js → chunk-FNQNJOHY.js} +89 -5
  19. package/dist/{chunk-ED4UPEJX.js → chunk-G7SIQFBQ.js} +1 -1
  20. package/dist/{chunk-TZWO7J4W.js → chunk-GCWAAPJ5.js} +115 -54
  21. package/dist/{chunk-YP3CSOZ6.js → chunk-GE7M3QTE.js} +142 -114
  22. package/dist/{chunk-LAFA56WD.js → chunk-HEII7W3Q.js} +1 -1
  23. package/dist/{chunk-3QRGCKYL.js → chunk-HWZWBJWL.js} +2 -2
  24. package/dist/{chunk-FKOIHGKV.js → chunk-JRH62XC4.js} +5 -1
  25. package/dist/{chunk-Q5DHVMXB.js → chunk-LZAOX76N.js} +18 -7
  26. package/dist/{chunk-B3SJXYIJ.js → chunk-NVXVEGGM.js} +1 -1
  27. package/dist/{chunk-ZVYLEF72.js → chunk-OXOU2FRS.js} +6 -6
  28. package/dist/chunk-QQKDGPUI.js +63 -0
  29. package/dist/{chunk-QTUESPAW.js → chunk-RFMQY56R.js} +1 -1
  30. package/dist/chunk-SYFVUF2C.js +65 -0
  31. package/dist/{chunk-Q62SDB53.js → chunk-TSCWSAQL.js} +2 -2
  32. package/dist/{chunk-DVM4ID64.js → chunk-UFHNSFAS.js} +89 -5
  33. package/dist/{chunk-PTI5H3RK.js → chunk-UIS7BVCX.js} +24 -13
  34. package/dist/{chunk-VZJVKQHH.js → chunk-WLV7TRMR.js} +1 -1
  35. package/dist/{chunk-N3VNOFXQ.js → chunk-Y2FNDKHF.js} +4 -4
  36. package/dist/{connected-teams-IJUJQ7R6.js → connected-teams-I2WZZZFA.js} +2 -2
  37. package/dist/{connected-teams-4A2AXDNN.js → connected-teams-XO766HB4.js} +2 -2
  38. package/dist/{coordinator-prompt-ZWBMAIWA.js → coordinator-prompt-LWYUZAXR.js} +6 -5
  39. package/dist/{coordinator-prompt-5GXGBGEZ.js → coordinator-prompt-ZK5MII7W.js} +6 -5
  40. package/dist/{global-workspace-OJRXWXEA.js → global-workspace-IB2CCEJF.js} +7 -6
  41. package/dist/{global-workspace-2SIPM4PW.js → global-workspace-T7RL3XEC.js} +7 -6
  42. package/dist/index.cjs +1010 -577
  43. package/dist/index.d.cts +96 -11
  44. package/dist/index.d.ts +96 -11
  45. package/dist/index.js +272 -93
  46. package/dist/mcp/run-stdio.cjs +981 -581
  47. package/dist/mcp/run-stdio.js +196 -43
  48. package/dist/{orchestrator-Z2O5OVJA.js → orchestrator-DPTRBKEH.js} +16 -13
  49. package/dist/{orchestrator-6TXQWBXN.js → orchestrator-Y5MWUU7C.js} +14 -11
  50. package/dist/{plan-file-6O7G4VPQ.js → plan-file-LSSSQGTQ.js} +2 -2
  51. package/dist/{plan-file-PHVKUAEE.js → plan-file-OZEBFSGQ.js} +2 -2
  52. package/dist/{run-XQKGHQZ2.js → run-CAGKZLHA.js} +1 -1
  53. package/dist/{run-USF6FRKV.js → run-EBWL2Q4N.js} +1 -1
  54. package/dist/{workspaces-UUJNOO4T.js → workspaces-VICQYI2N.js} +8 -7
  55. package/dist/{workspaces-3NUUZTQK.js → workspaces-ZXCUVCZC.js} +8 -7
  56. package/dist/{worktree-RZRJNHYL.js → worktree-DPIREDFR.js} +5 -4
  57. package/dist/{worktree-UCWWTVLS.js → worktree-HTUM35NT.js} +5 -4
  58. package/dist/worktree-exclude-N5X5I422.js +13 -0
  59. package/dist/worktree-exclude-X54WSOXM.js +11 -0
  60. package/package.json +1 -1
@@ -278,6 +278,7 @@ var DEFAULT_AGENTS = /* @__PURE__ */ new Set([
278
278
  "cursor"
279
279
  ]);
280
280
  var GITHUB_GIT_AUTH_MODES = ["auto", "gh", "ssh", "token"];
281
+ var FOLLOW_UP_BEHAVIORS = ["steer", "queue"];
281
282
  function emptyPublicIntegrations() {
282
283
  return {
283
284
  hasLinearApiKey: false,
@@ -601,6 +602,9 @@ function normalizeAdvanced(raw) {
601
602
  if (typeof source.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(source.orchestrationQuotaFallbackAgent) && source.orchestrationQuotaFallbackAgent !== "brightsy") {
602
603
  out.orchestrationQuotaFallbackAgent = source.orchestrationQuotaFallbackAgent;
603
604
  }
605
+ if (source.followUpBehavior === "queue" || source.followUpBehavior === "steer") {
606
+ out.followUpBehavior = source.followUpBehavior;
607
+ }
604
608
  return out;
605
609
  }
606
610
  function normalizeSettings(raw) {
@@ -1302,6 +1306,9 @@ function updateAdvancedSettings(patch) {
1302
1306
  if (typeof patch.orchestrationQuotaFallbackAgent === "string" && DEFAULT_AGENTS.has(patch.orchestrationQuotaFallbackAgent) && patch.orchestrationQuotaFallbackAgent !== "brightsy") {
1303
1307
  advanced.orchestrationQuotaFallbackAgent = patch.orchestrationQuotaFallbackAgent;
1304
1308
  }
1309
+ if (patch.followUpBehavior === "queue" || patch.followUpBehavior === "steer") {
1310
+ advanced.followUpBehavior = patch.followUpBehavior;
1311
+ }
1305
1312
  return saveAppSettings({ ...current, advanced });
1306
1313
  }
1307
1314
  function autoRenameBranchEnabled(settings = loadAppSettings()) {
@@ -1347,6 +1354,9 @@ function orchestrationQuotaFallbackAgent(settings = loadAppSettings()) {
1347
1354
  }
1348
1355
  return "cursor";
1349
1356
  }
1357
+ function followUpBehavior(settings = loadAppSettings()) {
1358
+ return settings.advanced.followUpBehavior === "queue" ? "queue" : "steer";
1359
+ }
1350
1360
  function maxConcurrentAgents(settings = loadAppSettings()) {
1351
1361
  const n = settings.advanced.maxConcurrent;
1352
1362
  if (typeof n === "number" && Number.isFinite(n)) {
@@ -1455,6 +1465,7 @@ export {
1455
1465
  issueSourceLabel,
1456
1466
  HARNESS_ENV_KEYS,
1457
1467
  GITHUB_GIT_AUTH_MODES,
1468
+ FOLLOW_UP_BEHAVIORS,
1458
1469
  emptyPublicIntegrations,
1459
1470
  toPublicAppSettings,
1460
1471
  appSettingsPath,
@@ -1508,6 +1519,7 @@ export {
1508
1519
  autoCleanupOrphansEnabled,
1509
1520
  orchestrationQuotaOnLimit,
1510
1521
  orchestrationQuotaFallbackAgent,
1522
+ followUpBehavior,
1511
1523
  maxConcurrentAgents,
1512
1524
  resolveClaudeExecutable,
1513
1525
  resolveAgentExecutable,
@@ -99,17 +99,93 @@ function withExportedPath(command, pathValue) {
99
99
  return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
100
100
  }
101
101
 
102
+ // src/git/github-agent-auth.ts
103
+ import { chmodSync, existsSync as existsSync2, mkdirSync, writeFileSync } from "fs";
104
+ import { homedir as homedir2 } from "os";
105
+ import { dirname, join as join2 } from "path";
106
+ function githubAgentAuthDir() {
107
+ const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
108
+ if (override) return override;
109
+ return join2(homedir2(), ".sideboard-git-auth");
110
+ }
111
+ function githubCredentialStorePath() {
112
+ return join2(githubAgentAuthDir(), "git-credentials");
113
+ }
114
+ function githubGhConfigDir() {
115
+ return join2(githubAgentAuthDir(), "gh");
116
+ }
117
+ function writePrivateFile(file, body) {
118
+ mkdirSync(dirname(file), { recursive: true, mode: 448 });
119
+ try {
120
+ chmodSync(dirname(file), 448);
121
+ } catch {
122
+ }
123
+ writeFileSync(file, body, { encoding: "utf8", mode: 384 });
124
+ try {
125
+ chmodSync(file, 384);
126
+ } catch {
127
+ }
128
+ }
129
+ function gitCredentialStoreContents(token) {
130
+ return `https://x-access-token:${encodeURIComponent(token)}@github.com
131
+ `;
132
+ }
133
+ function ghHostsYml(token, user = "x-access-token") {
134
+ const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
135
+ return [
136
+ "github.com:",
137
+ " git_protocol: https",
138
+ ` user: ${u}`,
139
+ ` oauth_token: ${token}`,
140
+ " users:",
141
+ ` ${u}:`,
142
+ ` oauth_token: ${token}`,
143
+ ""
144
+ ].join("\n");
145
+ }
146
+ function materializeGithubAgentAuth(token, user) {
147
+ const trimmed = token.trim();
148
+ if (!trimmed) return;
149
+ const root = githubAgentAuthDir();
150
+ mkdirSync(root, { recursive: true, mode: 448 });
151
+ try {
152
+ chmodSync(root, 448);
153
+ } catch {
154
+ }
155
+ writePrivateFile(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
156
+ const ghDir = githubGhConfigDir();
157
+ mkdirSync(ghDir, { recursive: true, mode: 448 });
158
+ writePrivateFile(join2(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
159
+ writePrivateFile(join2(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
160
+ }
161
+ function githubAgentAuthReady() {
162
+ return existsSync2(githubCredentialStorePath()) && existsSync2(join2(githubGhConfigDir(), "hosts.yml"));
163
+ }
164
+ function githubCredentialHelperGitConfig() {
165
+ const file = githubCredentialStorePath();
166
+ return [
167
+ { key: "credential.helper", value: "" },
168
+ { key: "credential.helper", value: `store --file=${file}` }
169
+ ];
170
+ }
171
+ function githubGhConfigEnv() {
172
+ return {
173
+ GH_CONFIG_DIR: githubGhConfigDir(),
174
+ GH_PROMPT_DISABLED: "1"
175
+ };
176
+ }
177
+
102
178
  // src/git/stale-lock.ts
103
- import { existsSync as existsSync2, statSync, unlinkSync } from "fs";
104
- import { join as join2 } from "path";
179
+ import { existsSync as existsSync3, statSync, unlinkSync } from "fs";
180
+ import { join as join3 } from "path";
105
181
  var STALE_INDEX_LOCK_MS = 2e4;
106
182
  function isIndexLockError(text) {
107
183
  return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text);
108
184
  }
109
185
  function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
110
- const lockPath = join2(gitDir, "index.lock");
186
+ const lockPath = join3(gitDir, "index.lock");
111
187
  try {
112
- if (!existsSync2(lockPath)) return null;
188
+ if (!existsSync3(lockPath)) return null;
113
189
  if (now - statSync(lockPath).mtimeMs < maxAgeMs) return null;
114
190
  unlinkSync(lockPath);
115
191
  return lockPath;
@@ -211,7 +287,10 @@ async function gh(args, cwd, opts) {
211
287
  timeoutMs: opts?.timeoutMs,
212
288
  env: {
213
289
  GH_PROMPT_DISABLED: "1",
214
- GIT_TERMINAL_PROMPT: "0"
290
+ GIT_TERMINAL_PROMPT: "0",
291
+ // Isolated hosts.yml uses git_protocol: https so `gh pr create` does not
292
+ // shell out over SSH when Settings → Git is SSH (ask_git in Electron).
293
+ ...githubAgentAuthReady() ? githubGhConfigEnv() : {}
215
294
  }
216
295
  });
217
296
  }
@@ -230,6 +309,11 @@ export {
230
309
  posixShellSingleQuote,
231
310
  resolveCommandBinarySync,
232
311
  withExportedPath,
312
+ githubAgentAuthDir,
313
+ materializeGithubAgentAuth,
314
+ githubAgentAuthReady,
315
+ githubCredentialHelperGitConfig,
316
+ githubGhConfigEnv,
233
317
  clearStaleIndexLocks,
234
318
  run,
235
319
  resolveGitDirsForLockRecovery,
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-S42XV45P.js";
10
10
  import {
11
11
  run
12
- } from "./chunk-KPIYENTF.js";
12
+ } from "./chunk-FNQNJOHY.js";
13
13
  import {
14
14
  appDataDir
15
15
  } from "./chunk-BD2ICC4D.js";
@@ -12,6 +12,7 @@ import {
12
12
  formatTurnExitError,
13
13
  getAdapter,
14
14
  isBrightsyNdjsonLine,
15
+ isInternalAgentStatusText,
15
16
  isPollWrapperToolName,
16
17
  isSessionQuotaLimit,
17
18
  liveActivitySummary,
@@ -32,21 +33,13 @@ import {
32
33
  summarizeTurnStderr,
33
34
  toolDescription,
34
35
  turnFailChatText
35
- } from "./chunk-Q5DHVMXB.js";
36
+ } from "./chunk-LZAOX76N.js";
36
37
  import {
37
38
  addWorkspace,
38
39
  ensureWorkspace,
39
40
  removeWorkspace,
40
41
  syncWorkspacesFromThreads
41
- } from "./chunk-Q62SDB53.js";
42
- import {
43
- extractPresentedPlan,
44
- readPlanFile,
45
- writePlanFile
46
- } from "./chunk-N5PM7HGQ.js";
47
- import {
48
- releaseCaffeinateHoldForThread
49
- } from "./chunk-KLBOWJ74.js";
42
+ } from "./chunk-TSCWSAQL.js";
50
43
  import {
51
44
  assertOrchestratorCapableAgent,
52
45
  attachmentsFromWorktreePaths,
@@ -63,14 +56,22 @@ import {
63
56
  persistPendingFileAttachments,
64
57
  stageAbsolutePathsAsAttachments,
65
58
  stageBuffersAsAttachments
66
- } from "./chunk-N3VNOFXQ.js";
59
+ } from "./chunk-Y2FNDKHF.js";
60
+ import {
61
+ extractPresentedPlan,
62
+ readPlanFile,
63
+ writePlanFile
64
+ } from "./chunk-2SDMENAL.js";
65
+ import {
66
+ releaseCaffeinateHoldForThread
67
+ } from "./chunk-KLBOWJ74.js";
67
68
  import {
68
69
  SLACK_REPLY_FORMATTING,
69
70
  coordinatorSystemPrompt,
70
71
  coordinatorTurnReminder,
71
72
  enrichWorkspacesWithGithub,
72
73
  ensureGlobalCoordinatorCwd
73
- } from "./chunk-ZVYLEF72.js";
74
+ } from "./chunk-OXOU2FRS.js";
74
75
  import {
75
76
  addPrStackLayer,
76
77
  allocateTeamName,
@@ -118,11 +119,11 @@ import {
118
119
  withRepoGitLock,
119
120
  worktreeDisplayLabelForGroup,
120
121
  worktreeNameFromPath
121
- } from "./chunk-JTPDWTWJ.js";
122
+ } from "./chunk-3JBMACYX.js";
122
123
  import {
123
124
  ATTACHMENTS_DIR,
124
125
  LEGACY_ATTACHMENTS_DIR
125
- } from "./chunk-B3SJXYIJ.js";
126
+ } from "./chunk-NVXVEGGM.js";
126
127
  import {
127
128
  appendMessage,
128
129
  createEmptyThread,
@@ -135,6 +136,9 @@ import {
135
136
  withThreadLock,
136
137
  writeThread
137
138
  } from "./chunk-EUXOHTUK.js";
139
+ import {
140
+ ensureWorktreeSideboardIgnored
141
+ } from "./chunk-SYFVUF2C.js";
138
142
  import {
139
143
  clearStaleIndexLocks,
140
144
  enrichPathWithNpmGlobalBin,
@@ -142,7 +146,7 @@ import {
142
146
  git,
143
147
  resolveGitDirsForLockRecovery,
144
148
  run
145
- } from "./chunk-KPIYENTF.js";
149
+ } from "./chunk-FNQNJOHY.js";
146
150
  import {
147
151
  childEnvWithAppSettings,
148
152
  getIssueSource,
@@ -158,7 +162,7 @@ import {
158
162
  stripNestedElectronEnv,
159
163
  updateAdvancedSettings,
160
164
  writeSecureJson
161
- } from "./chunk-BGQBELGJ.js";
165
+ } from "./chunk-CZD4NRDZ.js";
162
166
  import {
163
167
  writePrivateFile
164
168
  } from "./chunk-NSTQ6QKD.js";
@@ -391,7 +395,7 @@ async function continueSourceThread(threadId, prompt) {
391
395
  await continueOnReply(threadId, prompt);
392
396
  return;
393
397
  }
394
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-6TXQWBXN.js");
398
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-Y5MWUU7C.js");
395
399
  await getOrchestrator2().send(threadId, prompt);
396
400
  } catch {
397
401
  }
@@ -732,9 +736,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
732
736
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
733
737
  );
734
738
  }
735
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-2SIPM4PW.js");
739
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-T7RL3XEC.js");
736
740
  if (isGlobalThread2(thread)) {
737
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-5GXGBGEZ.js");
741
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-ZK5MII7W.js");
738
742
  ensureGlobalCoordinatorCwd2(
739
743
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
740
744
  );
@@ -1966,6 +1970,7 @@ async function runConventionSetup(repoPath, worktreePath, onLine, opts) {
1966
1970
  };
1967
1971
  }
1968
1972
  async function runWorkspaceSetup(repoPath, worktreePath, onLine, opts) {
1973
+ await ensureWorktreeSideboardIgnored(worktreePath);
1969
1974
  const reviewSkill = ensureReviewSkillFile(worktreePath);
1970
1975
  if (reviewSkill.wrote) {
1971
1976
  onLine?.(
@@ -2874,7 +2879,7 @@ async function createThread(input, _onSetupLine) {
2874
2879
  });
2875
2880
  await requireAgent(resolved.agent);
2876
2881
  if (input.cowboy) {
2877
- const { cowboyModeEnabled } = await import("./app-settings-ZCN632OJ.js");
2882
+ const { cowboyModeEnabled } = await import("./app-settings-J3JBCUOT.js");
2878
2883
  if (!cowboyModeEnabled()) {
2879
2884
  throw new Error(
2880
2885
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -2932,7 +2937,7 @@ async function createThread(input, _onSetupLine) {
2932
2937
  let sourceIsFork = false;
2933
2938
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
2934
2939
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
2935
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-DI55AJX3.js");
2940
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-CLC5UJC2.js");
2936
2941
  const task = await ensureAbleTimeTask({
2937
2942
  title: title?.trim() || "Untitled work",
2938
2943
  description: input.prompt?.trim() || void 0
@@ -3005,7 +3010,7 @@ async function createThread(input, _onSetupLine) {
3005
3010
  return readThread(thread.id) ?? thread;
3006
3011
  }
3007
3012
  async function listLinearIssues(agent, repoPath) {
3008
- const { getAdapter: getAdapter2 } = await import("./agents-V4MTDWXS.js");
3013
+ const { getAdapter: getAdapter2 } = await import("./agents-JAOMXDXN.js");
3009
3014
  await requireAgent(agent, { requireLinear: true });
3010
3015
  const adapter = getAdapter2(agent);
3011
3016
  if (!adapter.listLinearIssues) {
@@ -3397,7 +3402,7 @@ async function adoptThread(input) {
3397
3402
  throw new Error(`Worktree not found: ${input.worktreePath}`);
3398
3403
  }
3399
3404
  const repoPath = await resolveRepoRoot(input.worktreePath);
3400
- const { stdout: branch } = await import("./run-USF6FRKV.js").then(
3405
+ const { stdout: branch } = await import("./run-EBWL2Q4N.js").then(
3401
3406
  ({ git: git2 }) => git2(["rev-parse", "--abbrev-ref", "HEAD"], input.worktreePath)
3402
3407
  );
3403
3408
  const thread = createEmptyThread({
@@ -3412,8 +3417,10 @@ async function adoptThread(input) {
3412
3417
  messages: input.messages ?? []
3413
3418
  });
3414
3419
  writeThread(thread);
3415
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-UUJNOO4T.js");
3420
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-VICQYI2N.js");
3416
3421
  await ensureWorkspace2(repoPath);
3422
+ const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-N5X5I422.js");
3423
+ await ensureWorktreeSideboardIgnored2(input.worktreePath);
3417
3424
  return thread;
3418
3425
  }
3419
3426
  function listConductorWorkspaces() {
@@ -4709,7 +4716,7 @@ async function confirmLand(thread, opts) {
4709
4716
  if (preview.dirty) {
4710
4717
  committed = await commitAll(thread.worktreePath, meta.commitMessage);
4711
4718
  }
4712
- const { git: git2 } = await import("./run-USF6FRKV.js");
4719
+ const { git: git2 } = await import("./run-EBWL2Q4N.js");
4713
4720
  const { stdout: headOut } = await git2(
4714
4721
  ["rev-parse", "--abbrev-ref", "HEAD"],
4715
4722
  thread.worktreePath,
@@ -4771,7 +4778,7 @@ node <detached-job.js> wait <id> --until-done
4771
4778
  node <detached-job.js> status <id>
4772
4779
  \`\`\`
4773
4780
 
4774
- \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.sideboard/detached-jobs/<id>/\` (local scratch).
4781
+ \`<id>\` is kebab-case (\`mac-release\`, \`core-test\`, \`fly-deploy\`). State is \`.context/.sideboard/detached-jobs/<id>/\` (local scratch).
4775
4782
 
4776
4783
  Wait JSON:
4777
4784
 
@@ -5162,11 +5169,11 @@ function formatWorktreeDirective(thread, opts) {
5162
5169
  );
5163
5170
  } else if (opts?.githubSlug) {
5164
5171
  lines.push(
5165
- `- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name.`
5172
+ `- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short \`--body-file\` (limit 65,536 characters) \u2014 do not paste a changelog or diff into \`--body\`.`
5166
5173
  );
5167
5174
  } else {
5168
5175
  lines.push(
5169
- "- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name."
5176
+ "- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short `--body-file` (limit 65,536 characters) \u2014 do not paste a changelog or diff into `--body`."
5170
5177
  );
5171
5178
  }
5172
5179
  lines.push("");
@@ -5222,7 +5229,7 @@ function formatLongRunningDirective(opts) {
5222
5229
  "- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running` \u2014 the side column is the live view.",
5223
5230
  `- Loop \`${invoke} wait <id>\` (returns in ~45s). stillRunning \u2192 present the same id with \`content=delta\` only \u2192 wait again. Do not resend the full log or HTML.`,
5224
5231
  "- ok \u2192 finish the task. failed \u2192 read the log, fix, start once.",
5225
- "State: `.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
5232
+ "State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
5226
5233
  ].join("\n");
5227
5234
  }
5228
5235
  function formatLongRunningReminder(opts) {
@@ -5611,7 +5618,7 @@ function formatScheduledPrompt(name, prompt) {
5611
5618
  ${prompt}`;
5612
5619
  }
5613
5620
  async function defaultDeps() {
5614
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-6TXQWBXN.js");
5621
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-Y5MWUU7C.js");
5615
5622
  const orch = getOrchestrator2();
5616
5623
  return {
5617
5624
  findThread: (id) => findThreadByRef(id),
@@ -5715,6 +5722,7 @@ function armSchedules() {
5715
5722
  }
5716
5723
 
5717
5724
  // src/orchestrator/orchestrator.ts
5725
+ var LIVE_TURN_SPAWN_GRACE_MS = 15e3;
5718
5726
  function isPidAlive(pid) {
5719
5727
  if (!Number.isFinite(pid) || pid <= 0) return false;
5720
5728
  try {
@@ -5793,6 +5801,39 @@ var Orchestrator = class {
5793
5801
  if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return false;
5794
5802
  return true;
5795
5803
  }
5804
+ /**
5805
+ * Whether a child is actually turning — not leftover disk `running` after
5806
+ * the process died. Coordinators were telling users “Agent is running.
5807
+ * Waiting for gate to pass” from stale stillRunning.
5808
+ */
5809
+ threadLooksLive(thread) {
5810
+ if (thread.status === "queued") {
5811
+ if (this.draining.has(thread.id) || this.startingTurns.has(thread.id)) return true;
5812
+ return thread.queue.length > 0;
5813
+ }
5814
+ if (thread.status !== "running") return false;
5815
+ if (this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id)) return true;
5816
+ const pid = thread.agentPid;
5817
+ if (typeof pid === "number" && pid > 0 && isPidAlive(pid)) return true;
5818
+ const updated = Date.parse(thread.updatedAt ?? "");
5819
+ if (Number.isFinite(updated) && Date.now() - updated < LIVE_TURN_SPAWN_GRACE_MS) return true;
5820
+ return false;
5821
+ }
5822
+ /** Desktop-only: persist idle/stopped when MCP would otherwise keep reporting live. */
5823
+ healStaleReportedActivity(thread) {
5824
+ if (!thisProcessShouldDrainAgentQueues()) return thread;
5825
+ if (this.threadLooksLive(thread)) return thread;
5826
+ if (thread.status === "running") {
5827
+ this.healStaleRunningTurns();
5828
+ return readThread(thread.id) ?? thread;
5829
+ }
5830
+ if (thread.status === "queued" && thread.queue.length === 0 && !this.activeTurns.has(thread.id) && !this.startingTurns.has(thread.id) && !this.draining.has(thread.id)) {
5831
+ setStatus(thread.id, "idle");
5832
+ this.emit({ type: "status_changed", threadId: thread.id, status: "idle" });
5833
+ return readThread(thread.id) ?? thread;
5834
+ }
5835
+ return thread;
5836
+ }
5796
5837
  async reconcile(repoPath, opts) {
5797
5838
  const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
5798
5839
  const drainQueues = opts?.drainQueues !== false;
@@ -5836,7 +5877,7 @@ var Orchestrator = class {
5836
5877
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
5837
5878
  });
5838
5879
  }
5839
- const { autoCleanupOrphansEnabled } = await import("./app-settings-ZCN632OJ.js");
5880
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-J3JBCUOT.js");
5840
5881
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
5841
5882
  await cleanupOrphanWorktrees({ repoPaths });
5842
5883
  }
@@ -6076,7 +6117,7 @@ var Orchestrator = class {
6076
6117
  }
6077
6118
  await setup;
6078
6119
  if (skipSetup) return;
6079
- const { autoRunAfterSetupEnabled } = await import("./app-settings-ZCN632OJ.js");
6120
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-J3JBCUOT.js");
6080
6121
  if (autoRunAfterSetupEnabled()) {
6081
6122
  try {
6082
6123
  await this.startDev(threadId);
@@ -6127,12 +6168,14 @@ var Orchestrator = class {
6127
6168
  this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
6128
6169
  return thread;
6129
6170
  }
6130
- async send(threadRef, prompt) {
6171
+ async send(threadRef, prompt, opts) {
6131
6172
  const thread = this.requireThread(threadRef);
6132
6173
  if (thread.status === "archived") {
6133
6174
  throw new Error(`Thread is archived: ${thread.id}`);
6134
6175
  }
6135
- return withThreadLock(thread.id, async () => {
6176
+ const followUp = opts?.followUp === "steer" ? "steer" : "queue";
6177
+ let shouldSteer = false;
6178
+ const sent = await withThreadLock(thread.id, async () => {
6136
6179
  const current = this.requireThread(thread.id);
6137
6180
  if (current.status === "archived") {
6138
6181
  throw new Error(`Thread is archived: ${thread.id}`);
@@ -6141,6 +6184,7 @@ var Orchestrator = class {
6141
6184
  this.crashContinued.delete(thread.id);
6142
6185
  this.haltDrain.delete(thread.id);
6143
6186
  const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
6187
+ shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
6144
6188
  const patch = { queue };
6145
6189
  if (!inFlight) patch.status = "queued";
6146
6190
  const pid = current.agentPid;
@@ -6152,16 +6196,20 @@ var Orchestrator = class {
6152
6196
  if (!inFlight) {
6153
6197
  this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
6154
6198
  }
6155
- if (thisProcessShouldDrainAgentQueues()) {
6199
+ if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
6156
6200
  void this.drainQueue(thread.id);
6157
6201
  }
6158
6202
  return this.requireThread(thread.id);
6159
6203
  });
6204
+ if (shouldSteer && sent.queue.length > 0) {
6205
+ return this.sendQueuedMessageNow(sent.id, sent.queue.length - 1);
6206
+ }
6207
+ return sent;
6160
6208
  }
6161
- async fanOut(threadRefs, prompt) {
6209
+ async fanOut(threadRefs, prompt, opts) {
6162
6210
  const results = [];
6163
6211
  for (const ref of threadRefs) {
6164
- results.push(await this.send(ref, prompt));
6212
+ results.push(await this.send(ref, prompt, opts));
6165
6213
  }
6166
6214
  return results;
6167
6215
  }
@@ -6377,7 +6425,7 @@ var Orchestrator = class {
6377
6425
  }
6378
6426
  const isBrightsy = fresh.agent === "brightsy";
6379
6427
  const isOrchestration = isOrchestratorThread(fresh);
6380
- const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-ZCN632OJ.js");
6428
+ const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-J3JBCUOT.js");
6381
6429
  const gitAuthMode = getGithubGitAuthMode();
6382
6430
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
6383
6431
  githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
@@ -6965,8 +7013,8 @@ var Orchestrator = class {
6965
7013
  return created;
6966
7014
  }
6967
7015
  async waitForTurn(threadRef, timeoutMs = 6e5, opts) {
6968
- const thread = this.requireThread(threadRef);
6969
- if (!["running", "queued"].includes(thread.status)) {
7016
+ const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
7017
+ if (!this.threadLooksLive(thread)) {
6970
7018
  return thread;
6971
7019
  }
6972
7020
  const start = Date.now();
@@ -7003,12 +7051,13 @@ var Orchestrator = class {
7003
7051
  }
7004
7052
  });
7005
7053
  timer = setInterval(() => {
7006
- const current = readThread(thread.id);
7007
- if (!current) {
7054
+ const raw = readThread(thread.id);
7055
+ if (!raw) {
7008
7056
  finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
7009
7057
  return;
7010
7058
  }
7011
- if (!["running", "queued"].includes(current.status)) {
7059
+ const current = this.healStaleReportedActivity(raw);
7060
+ if (!this.threadLooksLive(current)) {
7012
7061
  finish(() => resolve(current));
7013
7062
  return;
7014
7063
  }
@@ -7031,20 +7080,22 @@ var Orchestrator = class {
7031
7080
  };
7032
7081
  }
7033
7082
  getTurnResult(threadRef) {
7034
- const thread = this.requireThread(threadRef);
7083
+ const thread = this.healStaleReportedActivity(this.requireThread(threadRef));
7035
7084
  const lastAgent = [...thread.messages].reverse().find((m) => m.role === "agent");
7036
7085
  const lastError = thread.lastError ?? null;
7037
- const text = (lastAgent?.text ?? "").trim() || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
7038
- const stillRunning = thread.status === "running" || thread.status === "queued";
7086
+ const rawText = (lastAgent?.text ?? "").trim();
7087
+ const text = (rawText && !isInternalAgentStatusText(rawText) ? rawText : "") || (thread.status === "error" || thread.status === "stopped" || thread.status === "broken" ? lastError ?? "" : "");
7088
+ const stillRunning = this.threadLooksLive(thread);
7039
7089
  const live = stillRunning ? readTurnLive(thread.id) : null;
7040
- const queuedHint = thread.status === "queued" && !live?.summary ? "Queued \u2014 waiting for a concurrency slot" : null;
7090
+ const liveSummary = live?.summary && !isInternalAgentStatusText(live.summary) ? live.summary : null;
7091
+ const queuedHint = stillRunning && thread.status === "queued" && !liveSummary ? "Queued \u2014 waiting for a concurrency slot" : null;
7041
7092
  return {
7042
7093
  text,
7043
7094
  status: thread.status,
7044
7095
  sessionId: thread.sessionId,
7045
7096
  lastError,
7046
7097
  stillRunning,
7047
- progress: live?.summary ?? queuedHint,
7098
+ progress: liveSummary ?? queuedHint,
7048
7099
  lastActivityAt: live?.updatedAt ?? null,
7049
7100
  usage: lastAgent?.usage ?? null
7050
7101
  };
@@ -7237,7 +7288,7 @@ var Orchestrator = class {
7237
7288
  updateThread(thread.id, { title: meta.title });
7238
7289
  }
7239
7290
  }
7240
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-ZCN632OJ.js");
7291
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-J3JBCUOT.js");
7241
7292
  const latest = this.requireThread(thread.id);
7242
7293
  if (!shouldAutoArchiveOnPrMerge({
7243
7294
  previousPrState: prevState || null,
@@ -7392,7 +7443,14 @@ var Orchestrator = class {
7392
7443
  );
7393
7444
  }
7394
7445
  if ((action === "commit-push" || action === "create-draft" || action === "create-web") && thread.worktreePath?.trim() && !await isDirty(thread.worktreePath)) {
7395
- await this.pushAndMaybeOpenPr(thread, action);
7446
+ try {
7447
+ await this.pushAndMaybeOpenPr(thread, action);
7448
+ } catch (err) {
7449
+ const message = err instanceof Error ? err.message : String(err);
7450
+ updateThread(thread.id, { lastError: message });
7451
+ this.emit({ type: "error", threadId: thread.id, message });
7452
+ throw err;
7453
+ }
7396
7454
  return this.requireThread(threadRef);
7397
7455
  }
7398
7456
  let prBase;
@@ -7547,7 +7605,7 @@ var Orchestrator = class {
7547
7605
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
7548
7606
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
7549
7607
  try {
7550
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-UUJNOO4T.js");
7608
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-VICQYI2N.js");
7551
7609
  await ensureWorkspace2(thread.repoPath);
7552
7610
  } catch {
7553
7611
  }
@@ -7574,7 +7632,7 @@ var Orchestrator = class {
7574
7632
  await runArchiveScript(thread.repoPath, thread.worktreePath);
7575
7633
  } catch {
7576
7634
  }
7577
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-ZCN632OJ.js");
7635
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-J3JBCUOT.js");
7578
7636
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
7579
7637
  await removeWorktree(thread.repoPath, thread.worktreePath, {
7580
7638
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -7601,12 +7659,14 @@ var Orchestrator = class {
7601
7659
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
7602
7660
  );
7603
7661
  }
7604
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-UCWWTVLS.js");
7662
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-HTUM35NT.js");
7605
7663
  const slug = thread.worktreePath.split("/").pop();
7606
7664
  const dest = thread.worktreePath;
7607
7665
  await withRepoGitLock(thread.repoPath, async () => {
7608
7666
  await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
7609
7667
  });
7668
+ const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-N5X5I422.js");
7669
+ await ensureWorktreeSideboardIgnored2(dest);
7610
7670
  void createThreadWorktree2;
7611
7671
  void slug;
7612
7672
  }
@@ -7709,7 +7769,7 @@ async function startOrchestration(opts) {
7709
7769
  sourceRef: "default",
7710
7770
  ...createOpts
7711
7771
  }).catch(async () => {
7712
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-UCWWTVLS.js");
7772
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-HTUM35NT.js");
7713
7773
  const repo = await resolveRepoRoot2(repoPath);
7714
7774
  const def = await resolveDefaultBranch2(repo);
7715
7775
  return orch.createThread({
@@ -7761,6 +7821,7 @@ export {
7761
7821
  updateSchedule,
7762
7822
  deleteSchedule,
7763
7823
  fireSchedule,
7824
+ LIVE_TURN_SPAWN_GRACE_MS,
7764
7825
  isPidAlive,
7765
7826
  waitForPidExit,
7766
7827
  Orchestrator,