@sideboard-ai/core 0.1.191 → 0.1.192

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.
@@ -38,11 +38,11 @@ import {
38
38
  resolveQuotaFallbackAgent,
39
39
  turnCostUsdFromCursorUsage,
40
40
  whichOnPath
41
- } from "./chunk-GBWKMWUQ.js";
41
+ } from "./chunk-WHD4JNTN.js";
42
42
  import "./chunk-HVIEYTUK.js";
43
43
  import "./chunk-Y4MIXGPA.js";
44
44
  import "./chunk-VKQGAWHY.js";
45
- import "./chunk-XXEIF2IL.js";
45
+ import "./chunk-7NSXGL6L.js";
46
46
  import "./chunk-XBLN52RZ.js";
47
47
  import "./chunk-D6JWYJ4P.js";
48
48
  import "./chunk-GOZ6T3AG.js";
@@ -32,8 +32,8 @@ import {
32
32
  resolveLoginCommand,
33
33
  resolveQuotaFallbackAgent,
34
34
  whichOnPath
35
- } from "./chunk-OLDZXO53.js";
36
- import "./chunk-VIODP5PT.js";
35
+ } from "./chunk-TWSCTJCR.js";
36
+ import "./chunk-VV7UT3E2.js";
37
37
  import "./chunk-WXKXSZN4.js";
38
38
  import "./chunk-6K64FJDD.js";
39
39
  import "./chunk-IEEAVWAP.js";
@@ -350,8 +350,8 @@ var COORDINATOR_TOOL_PLAYBOOK = [
350
350
  "- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
351
351
  "- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
352
352
  "- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
353
- "- send_to_thread \u2014 queue a prompt (start/continue a chat turn). force_stop: true only to replace a wrong in-flight request \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that kills the child mid-thought)",
354
- "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
353
+ "- send_to_thread \u2014 steer a prompt (start/continue a chat turn; Settings \u2192 Follow-up, default steer: interrupt and start now). force_stop: true only to replace a wrong in-flight request and clear the inbox \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that interrupts the child mid-thought)",
354
+ "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send_to_thread a check-in (that steers / interrupts). Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
355
355
  "- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
356
356
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
357
357
  "Setup / run:",
@@ -361,7 +361,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
361
361
  "- get_diff \u2014 compact diff summary",
362
362
  "- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
363
363
  '- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id. The review stays in that chat so they can read it and type next steps \u2014 do not tell the child to comment or update the PR or ticket.',
364
- "- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
364
+ "- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it steers the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
365
365
  '- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
366
366
  '- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Ready for review.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
367
367
  "Process guides:",
@@ -33,7 +33,7 @@ import {
33
33
  summarizeTurnStderr,
34
34
  toolDescription,
35
35
  turnFailChatText
36
- } from "./chunk-GBWKMWUQ.js";
36
+ } from "./chunk-WHD4JNTN.js";
37
37
  import {
38
38
  extractPresentedPlan,
39
39
  readPlanFile,
@@ -64,7 +64,7 @@ import {
64
64
  stageAbsolutePathsAsAttachments,
65
65
  stageBuffersAsAttachments,
66
66
  syncWorkspacesFromThreads
67
- } from "./chunk-XXEIF2IL.js";
67
+ } from "./chunk-7NSXGL6L.js";
68
68
  import {
69
69
  addPrStackLayer,
70
70
  allocateTeamName,
@@ -402,7 +402,7 @@ async function continueSourceThread(threadId, prompt) {
402
402
  await continueOnReply(threadId, prompt);
403
403
  return;
404
404
  }
405
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-2X6LYBQI.js");
405
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-4G76BOHH.js");
406
406
  await getOrchestrator2().send(threadId, prompt);
407
407
  } catch {
408
408
  }
@@ -795,9 +795,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
795
795
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
796
796
  );
797
797
  }
798
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-6G5JJH2E.js");
798
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-2BVCJUAL.js");
799
799
  if (isGlobalThread2(thread)) {
800
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-LWKOL3AZ.js");
800
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-PNUDN4DW.js");
801
801
  ensureGlobalCoordinatorCwd2(
802
802
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
803
803
  );
@@ -2658,8 +2658,8 @@ function mcpWaitForTurnTimeoutMs(requested) {
2658
2658
  if (!Number.isFinite(n)) return MCP_WAIT_FOR_TURN_MAX_MS;
2659
2659
  return Math.min(Math.max(1e3, Math.floor(n)), MCP_WAIT_FOR_TURN_MAX_MS);
2660
2660
  }
2661
- var MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send a check-in prompt or assume a hang while progress is updating.";
2662
- var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume it failed to start.";
2661
+ var MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts) or assume a hang while progress is updating.";
2662
+ var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume it failed to start.";
2663
2663
  function mcpWaitStillRunningHint(status) {
2664
2664
  return status === "queued" ? MCP_WAIT_QUEUED_HINT : MCP_WAIT_STILL_RUNNING_HINT;
2665
2665
  }
@@ -4155,7 +4155,7 @@ async function adoptThread(input) {
4155
4155
  messages: input.messages ?? []
4156
4156
  });
4157
4157
  writeThread(thread);
4158
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-LMFCRXTT.js");
4158
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-OY7D5RPU.js");
4159
4159
  await ensureWorkspace2(repoPath);
4160
4160
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-N5X5I422.js");
4161
4161
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -6458,7 +6458,7 @@ function formatScheduledPrompt(name, prompt) {
6458
6458
  ${prompt}`;
6459
6459
  }
6460
6460
  async function defaultDeps() {
6461
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-2X6LYBQI.js");
6461
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-4G76BOHH.js");
6462
6462
  const orch = getOrchestrator2();
6463
6463
  return {
6464
6464
  findThread: (id) => findThreadByRef(id),
@@ -6589,6 +6589,10 @@ function resolveSendFollowUp(thread, requested) {
6589
6589
  if (requested === "steer" || requested === "queue") return requested;
6590
6590
  return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
6591
6591
  }
6592
+ function resolveOrchChildFollowUp(requested) {
6593
+ if (requested === "steer" || requested === "queue") return requested;
6594
+ return followUpBehavior();
6595
+ }
6592
6596
  var STALE_AGENT_PID_WAIT_MS = 2500;
6593
6597
  function writeLiveStatus(threadId, status, lastError) {
6594
6598
  const latest = readThread(threadId);
@@ -8401,7 +8405,7 @@ var Orchestrator = class {
8401
8405
  /**
8402
8406
  * Desktop git buttons + MCP `ask_git`.
8403
8407
  * When the worktree is clean, push / open the PR here (HTTPS via `gh` if SSH
8404
- * is missing). When dirty, queue the worktree agent to commit first.
8408
+ * is missing). When dirty, steer the worktree agent to commit first.
8405
8409
  */
8406
8410
  async askGit(threadRef, action) {
8407
8411
  if (!AGENT_GIT_ACTIONS.includes(action)) {
@@ -8438,7 +8442,9 @@ var Orchestrator = class {
8438
8442
  } catch {
8439
8443
  }
8440
8444
  }
8441
- return this.send(threadRef, agentGitPrompt(action, { prBase }));
8445
+ return this.send(threadRef, agentGitPrompt(action, { prBase }), {
8446
+ followUp: resolveOrchChildFollowUp()
8447
+ });
8442
8448
  }
8443
8449
  /** Push origin (gh HTTPS fallback) and create/update the PR when requested. */
8444
8450
  async pushAndMaybeOpenPr(thread, action) {
@@ -8582,7 +8588,7 @@ var Orchestrator = class {
8582
8588
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
8583
8589
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
8584
8590
  try {
8585
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-LMFCRXTT.js");
8591
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-OY7D5RPU.js");
8586
8592
  await ensureWorkspace2(thread.repoPath);
8587
8593
  } catch {
8588
8594
  }
@@ -8807,6 +8813,7 @@ export {
8807
8813
  isPidAlive,
8808
8814
  waitForPidExit,
8809
8815
  resolveSendFollowUp,
8816
+ resolveOrchChildFollowUp,
8810
8817
  Orchestrator,
8811
8818
  getOrchestrator,
8812
8819
  startOrchestration
@@ -24,7 +24,7 @@ import {
24
24
  stripBrightsyNdjsonNoise,
25
25
  sumUsageList,
26
26
  toolDescription
27
- } from "./chunk-OLDZXO53.js";
27
+ } from "./chunk-TWSCTJCR.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-VIODP5PT.js";
50
+ } from "./chunk-VV7UT3E2.js";
51
51
  import {
52
52
  addPrStackLayer,
53
53
  allocateTeamName,
@@ -467,7 +467,7 @@ async function continueSourceThread(threadId, prompt) {
467
467
  await continueOnReply(threadId, prompt);
468
468
  return;
469
469
  }
470
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-F3CXDBZB.js");
470
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-LWEZ74RK.js");
471
471
  await getOrchestrator2().send(threadId, prompt);
472
472
  } catch {
473
473
  }
@@ -801,9 +801,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
801
801
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
802
802
  );
803
803
  }
804
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-XATJTV3N.js");
804
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-JTBBH2K5.js");
805
805
  if (isGlobalThread2(thread)) {
806
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-MSC44OOM.js");
806
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-S4HHFSLI.js");
807
807
  ensureGlobalCoordinatorCwd2(
808
808
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
809
809
  );
@@ -2745,8 +2745,8 @@ function mcpWaitForTurnTimeoutMs(requested) {
2745
2745
  if (!Number.isFinite(n)) return MCP_WAIT_FOR_TURN_MAX_MS;
2746
2746
  return Math.min(Math.max(1e3, Math.floor(n)), MCP_WAIT_FOR_TURN_MAX_MS);
2747
2747
  }
2748
- var MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send a check-in prompt or assume a hang while progress is updating.";
2749
- var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume it failed to start.";
2748
+ var MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts) or assume a hang while progress is updating.";
2749
+ var MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume it failed to start.";
2750
2750
  function mcpWaitStillRunningHint(status) {
2751
2751
  return status === "queued" ? MCP_WAIT_QUEUED_HINT : MCP_WAIT_STILL_RUNNING_HINT;
2752
2752
  }
@@ -3874,7 +3874,7 @@ async function createThread(input, _onSetupLine) {
3874
3874
  return readThread(thread.id) ?? thread;
3875
3875
  }
3876
3876
  async function listLinearIssues(agent, repoPath) {
3877
- const { getAdapter: getAdapter2 } = await import("./agents-DTPVTDB5.js");
3877
+ const { getAdapter: getAdapter2 } = await import("./agents-TXGQIK2E.js");
3878
3878
  await requireAgent(agent, { requireLinear: true });
3879
3879
  const adapter = getAdapter2(agent);
3880
3880
  if (!adapter.listLinearIssues) {
@@ -4296,7 +4296,7 @@ async function adoptThread(input) {
4296
4296
  messages: input.messages ?? []
4297
4297
  });
4298
4298
  writeThread(thread);
4299
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-FWKPWSXV.js");
4299
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-ZYPME3YD.js");
4300
4300
  await ensureWorkspace2(repoPath);
4301
4301
  const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
4302
4302
  await ensureWorktreeSideboardIgnored2(input.worktreePath);
@@ -6805,7 +6805,7 @@ function formatScheduledPrompt(name, prompt) {
6805
6805
  ${prompt}`;
6806
6806
  }
6807
6807
  async function defaultDeps() {
6808
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-F3CXDBZB.js");
6808
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-LWEZ74RK.js");
6809
6809
  const orch = getOrchestrator2();
6810
6810
  return {
6811
6811
  findThread: (id) => findThreadByRef(id),
@@ -6936,6 +6936,10 @@ function resolveSendFollowUp(thread, requested) {
6936
6936
  if (requested === "steer" || requested === "queue") return requested;
6937
6937
  return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
6938
6938
  }
6939
+ function resolveOrchChildFollowUp(requested) {
6940
+ if (requested === "steer" || requested === "queue") return requested;
6941
+ return followUpBehavior();
6942
+ }
6939
6943
  var STALE_AGENT_PID_WAIT_MS = 2500;
6940
6944
  function writeLiveStatus(threadId, status, lastError) {
6941
6945
  const latest = readThread(threadId);
@@ -8748,7 +8752,7 @@ var Orchestrator = class {
8748
8752
  /**
8749
8753
  * Desktop git buttons + MCP `ask_git`.
8750
8754
  * When the worktree is clean, push / open the PR here (HTTPS via `gh` if SSH
8751
- * is missing). When dirty, queue the worktree agent to commit first.
8755
+ * is missing). When dirty, steer the worktree agent to commit first.
8752
8756
  */
8753
8757
  async askGit(threadRef, action) {
8754
8758
  if (!AGENT_GIT_ACTIONS.includes(action)) {
@@ -8785,7 +8789,9 @@ var Orchestrator = class {
8785
8789
  } catch {
8786
8790
  }
8787
8791
  }
8788
- return this.send(threadRef, agentGitPrompt(action, { prBase }));
8792
+ return this.send(threadRef, agentGitPrompt(action, { prBase }), {
8793
+ followUp: resolveOrchChildFollowUp()
8794
+ });
8789
8795
  }
8790
8796
  /** Push origin (gh HTTPS fallback) and create/update the PR when requested. */
8791
8797
  async pushAndMaybeOpenPr(thread, action) {
@@ -8929,7 +8935,7 @@ var Orchestrator = class {
8929
8935
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
8930
8936
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
8931
8937
  try {
8932
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-FWKPWSXV.js");
8938
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-ZYPME3YD.js");
8933
8939
  await ensureWorkspace2(thread.repoPath);
8934
8940
  } catch {
8935
8941
  }
@@ -9348,6 +9354,7 @@ export {
9348
9354
  isPidAlive,
9349
9355
  waitForPidExit,
9350
9356
  resolveSendFollowUp,
9357
+ resolveOrchChildFollowUp,
9351
9358
  Orchestrator,
9352
9359
  getOrchestrator,
9353
9360
  startOrchestration,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isOrchestratorThread
3
- } from "./chunk-VIODP5PT.js";
3
+ } from "./chunk-VV7UT3E2.js";
4
4
  import {
5
5
  codexUnattendedGitConfigArgs,
6
6
  mergeAgentGitAuthEnv,
@@ -1908,7 +1908,7 @@ var claudeAdapter = {
1908
1908
  );
1909
1909
  }
1910
1910
  const mode = permissionMode(thread);
1911
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-XATJTV3N.js");
1911
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-JTBBH2K5.js");
1912
1912
  const isOrchestrator = isOrchestratorThread2(thread);
1913
1913
  const injectedServers = await buildInjectedMcpServers({
1914
1914
  includeSideboard: true,
@@ -395,8 +395,8 @@ var COORDINATOR_TOOL_PLAYBOOK = [
395
395
  "- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
396
396
  "- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
397
397
  "- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
398
- "- send_to_thread \u2014 queue a prompt (start/continue a chat turn). force_stop: true only to replace a wrong in-flight request \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that kills the child mid-thought)",
399
- "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
398
+ "- send_to_thread \u2014 steer a prompt (start/continue a chat turn; Settings \u2192 Follow-up, default steer: interrupt and start now). force_stop: true only to replace a wrong in-flight request and clear the inbox \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that interrupts the child mid-thought)",
399
+ "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send_to_thread a check-in (that steers / interrupts). Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
400
400
  "- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
401
401
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
402
402
  "Setup / run:",
@@ -406,7 +406,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
406
406
  "- get_diff \u2014 compact diff summary",
407
407
  "- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
408
408
  '- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id. The review stays in that chat so they can read it and type next steps \u2014 do not tell the child to comment or update the PR or ticket.',
409
- "- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
409
+ "- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it steers the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
410
410
  '- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
411
411
  '- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Ready for review.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
412
412
  "Process guides:",
@@ -11,7 +11,7 @@ import {
11
11
  } from "./chunk-Y4MIXGPA.js";
12
12
  import {
13
13
  isOrchestratorThread
14
- } from "./chunk-XXEIF2IL.js";
14
+ } from "./chunk-7NSXGL6L.js";
15
15
  import {
16
16
  codexUnattendedGitConfigArgs,
17
17
  mergeAgentGitAuthEnv,
@@ -2390,7 +2390,7 @@ var claudeAdapter = {
2390
2390
  );
2391
2391
  }
2392
2392
  const mode = permissionMode(thread);
2393
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-6G5JJH2E.js");
2393
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-2BVCJUAL.js");
2394
2394
  const isOrchestrator = isOrchestratorThread2(thread);
2395
2395
  const injectedServers = await buildInjectedMcpServers({
2396
2396
  includeSideboard: true,
@@ -9,7 +9,7 @@ import {
9
9
  enrichWorkspacesWithGithub,
10
10
  ensureGlobalCoordinatorCwd,
11
11
  formatWorkspaceInventory
12
- } from "./chunk-XXEIF2IL.js";
12
+ } from "./chunk-7NSXGL6L.js";
13
13
  import "./chunk-XBLN52RZ.js";
14
14
  import "./chunk-D6JWYJ4P.js";
15
15
  import "./chunk-GOZ6T3AG.js";
@@ -7,7 +7,7 @@ import {
7
7
  enrichWorkspacesWithGithub,
8
8
  ensureGlobalCoordinatorCwd,
9
9
  formatWorkspaceInventory
10
- } from "./chunk-VIODP5PT.js";
10
+ } from "./chunk-VV7UT3E2.js";
11
11
  import "./chunk-WXKXSZN4.js";
12
12
  import "./chunk-6K64FJDD.js";
13
13
  import "./chunk-J7LQVLFQ.js";
@@ -17,7 +17,7 @@ import {
17
17
  orchestratorSessionPoisonedByBuiltins,
18
18
  slackCoordinatorSourceRef,
19
19
  takenTeamSlugsForOrchestration
20
- } from "./chunk-XXEIF2IL.js";
20
+ } from "./chunk-7NSXGL6L.js";
21
21
  import "./chunk-XBLN52RZ.js";
22
22
  import "./chunk-D6JWYJ4P.js";
23
23
  import "./chunk-GOZ6T3AG.js";
@@ -15,7 +15,7 @@ import {
15
15
  orchestratorSessionPoisonedByBuiltins,
16
16
  slackCoordinatorSourceRef,
17
17
  takenTeamSlugsForOrchestration
18
- } from "./chunk-VIODP5PT.js";
18
+ } from "./chunk-VV7UT3E2.js";
19
19
  import "./chunk-WXKXSZN4.js";
20
20
  import "./chunk-6K64FJDD.js";
21
21
  import "./chunk-J7LQVLFQ.js";
package/dist/index.cjs CHANGED
@@ -7772,8 +7772,8 @@ var init_coordinator_prompt = __esm({
7772
7772
  "- start_board_card \u2014 same as create_thread for a ticket/PR/named branch (attaches issue text when resolvable). Then send_to_thread.",
7773
7773
  "- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
7774
7774
  "- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
7775
- "- send_to_thread \u2014 queue a prompt (start/continue a chat turn). force_stop: true only to replace a wrong in-flight request \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that kills the child mid-thought)",
7776
- "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
7775
+ "- send_to_thread \u2014 steer a prompt (start/continue a chat turn; Settings \u2192 Follow-up, default steer: interrupt and start now). force_stop: true only to replace a wrong in-flight request and clear the inbox \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that interrupts the child mid-thought)",
7776
+ "- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send_to_thread a check-in (that steers / interrupts). Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
7777
7777
  "- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
7778
7778
  "- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
7779
7779
  "Setup / run:",
@@ -7783,7 +7783,7 @@ var init_coordinator_prompt = __esm({
7783
7783
  "- get_diff \u2014 compact diff summary",
7784
7784
  "- get_pr_checks \u2014 snapshot of a worktree thread's PR checks (null = no PR). Use this to inspect status. If the user gave a goal, the worktree agent watches with `gh pr checks --watch` \u2014 do not poll for the human.",
7785
7785
  '- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else .context/review.md copied from .sideboard/review.md / stock; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id. The review stays in that chat so they can read it and type next steps \u2014 do not tell the child to comment or update the PR or ticket.',
7786
- "- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
7786
+ "- ask_git \u2014 commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it steers the worktree agent \u2014 then wait_for_turn (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error. If the user gave a goal (Greptile 5/5, CI green), send_to_thread that goal so the worktree agent enters the watch-fix-push loop \u2014 do not tell the human to poll.",
7787
7787
  '- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
7788
7788
  '- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Ready for review.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
7789
7789
  "Process guides:",
@@ -15956,8 +15956,8 @@ var init_wait_for_turn = __esm({
15956
15956
  "src/mcp/wait-for-turn.ts"() {
15957
15957
  "use strict";
15958
15958
  MCP_WAIT_FOR_TURN_MAX_MS = 45e3;
15959
- MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send a check-in prompt or assume a hang while progress is updating.";
15960
- MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume it failed to start.";
15959
+ MCP_WAIT_STILL_RUNNING_HINT = "Child is still working. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts) or assume a hang while progress is updating.";
15960
+ MCP_WAIT_QUEUED_HINT = "Child is queued waiting for a concurrency slot \u2014 it has not started yet. Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume it failed to start.";
15961
15961
  MCP_WAIT_STOPPED_HINT = "Child was stopped before the turn finished. Do not treat this as success. send_to_thread to resume, or tell the user.";
15962
15962
  MCP_WAIT_BROKEN_HINT = "Child worktree is broken (missing on disk). Tell the user \u2014 do not treat this as success.";
15963
15963
  MCP_WAIT_ERROR_HINT = "Child turn failed. lastError/text is the failure \u2014 switch agent, tell the user, or retry. Do not treat empty text as success.";
@@ -20831,6 +20831,7 @@ __export(orchestrator_exports, {
20831
20831
  Orchestrator: () => Orchestrator,
20832
20832
  getOrchestrator: () => getOrchestrator,
20833
20833
  isPidAlive: () => isPidAlive,
20834
+ resolveOrchChildFollowUp: () => resolveOrchChildFollowUp,
20834
20835
  resolveSendFollowUp: () => resolveSendFollowUp,
20835
20836
  startOrchestration: () => startOrchestration,
20836
20837
  waitForPidExit: () => waitForPidExit
@@ -20861,6 +20862,10 @@ function resolveSendFollowUp(thread, requested) {
20861
20862
  if (requested === "steer" || requested === "queue") return requested;
20862
20863
  return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
20863
20864
  }
20865
+ function resolveOrchChildFollowUp(requested) {
20866
+ if (requested === "steer" || requested === "queue") return requested;
20867
+ return followUpBehavior();
20868
+ }
20864
20869
  function writeLiveStatus(threadId, status, lastError) {
20865
20870
  const latest = readThread(threadId);
20866
20871
  if (!latest || latest.status === "archived") return latest;
@@ -22801,7 +22806,7 @@ var init_orchestrator = __esm({
22801
22806
  /**
22802
22807
  * Desktop git buttons + MCP `ask_git`.
22803
22808
  * When the worktree is clean, push / open the PR here (HTTPS via `gh` if SSH
22804
- * is missing). When dirty, queue the worktree agent to commit first.
22809
+ * is missing). When dirty, steer the worktree agent to commit first.
22805
22810
  */
22806
22811
  async askGit(threadRef, action) {
22807
22812
  if (!AGENT_GIT_ACTIONS.includes(action)) {
@@ -22838,7 +22843,9 @@ var init_orchestrator = __esm({
22838
22843
  } catch {
22839
22844
  }
22840
22845
  }
22841
- return this.send(threadRef, agentGitPrompt(action, { prBase }));
22846
+ return this.send(threadRef, agentGitPrompt(action, { prBase }), {
22847
+ followUp: resolveOrchChildFollowUp()
22848
+ });
22842
22849
  }
22843
22850
  /** Push origin (gh HTTPS fallback) and create/update the PR when requested. */
22844
22851
  async pushAndMaybeOpenPr(thread, action) {
@@ -23859,6 +23866,7 @@ __export(index_exports, {
23859
23866
  resolveLoginCommand: () => resolveLoginCommand,
23860
23867
  resolveNewOrchestratorOptions: () => resolveNewOrchestratorOptions,
23861
23868
  resolveNewThreadOptions: () => resolveNewThreadOptions,
23869
+ resolveOrchChildFollowUp: () => resolveOrchChildFollowUp,
23862
23870
  resolveOrchestratorDefaults: () => resolveOrchestratorDefaults,
23863
23871
  resolvePlanMarkdown: () => resolvePlanMarkdown,
23864
23872
  resolvePrSelector: () => resolvePrSelector,
@@ -24605,6 +24613,16 @@ query SideboardLabels($first: Int!) {
24605
24613
  }
24606
24614
  }
24607
24615
  `;
24616
+ var TEAM_LABELS_QUERY = `
24617
+ query SideboardTeamLabels($id: String!, $first: Int!, $after: String) {
24618
+ team(id: $id) {
24619
+ labels(first: $first, after: $after) {
24620
+ nodes { id name }
24621
+ pageInfo { hasNextPage endCursor }
24622
+ }
24623
+ }
24624
+ }
24625
+ `;
24608
24626
  var PROJECTS_QUERY = `
24609
24627
  query SideboardProjects($first: Int!, $filter: ProjectFilter) {
24610
24628
  projects(first: $first, filter: $filter) {
@@ -24978,15 +24996,38 @@ function formatRelationList(relations) {
24978
24996
  if (!relations.length) return "(none)";
24979
24997
  return relations.map((r) => `${r.type} ${r.issue.identifier || r.issue.id}`).join(", ");
24980
24998
  }
24981
- async function listLinearLabels(opts) {
24982
- const json = await linearGraphql(LABELS_QUERY, { first: 250 }, opts);
24983
- return (json.issueLabels?.nodes ?? []).flatMap((node) => {
24999
+ function mapLabelNodes(nodes) {
25000
+ return (nodes ?? []).flatMap((node) => {
24984
25001
  const id = String(node.id ?? "").trim();
24985
25002
  const name = String(node.name ?? "").trim();
24986
25003
  if (!id) return [];
24987
25004
  return [{ id, name }];
24988
25005
  });
24989
25006
  }
25007
+ async function listLinearWorkspaceLabels(opts) {
25008
+ const json = await linearGraphql(LABELS_QUERY, { first: 250 }, opts);
25009
+ return mapLabelNodes(json.issueLabels?.nodes);
25010
+ }
25011
+ async function listLinearLabels(opts) {
25012
+ const teamId = opts?.teamId?.trim();
25013
+ if (teamId) {
25014
+ const out = [];
25015
+ let after;
25016
+ for (let page = 0; page < 4; page++) {
25017
+ const json = await linearGraphql(
25018
+ TEAM_LABELS_QUERY,
25019
+ after ? { id: teamId, first: 250, after } : { id: teamId, first: 250 },
25020
+ opts
25021
+ );
25022
+ const conn = json.team?.labels;
25023
+ out.push(...mapLabelNodes(conn?.nodes));
25024
+ if (!conn?.pageInfo?.hasNextPage || !conn.pageInfo.endCursor) break;
25025
+ after = conn.pageInfo.endCursor;
25026
+ }
25027
+ if (out.length) return out;
25028
+ }
25029
+ return listLinearWorkspaceLabels(opts);
25030
+ }
24990
25031
  async function listLinearProjects(filter, opts) {
24991
25032
  const json = await linearGraphql(PROJECTS_QUERY, { first: 50, filter: filter ?? {} }, opts);
24992
25033
  return (json.projects?.nodes ?? []).flatMap((node) => {
@@ -25281,7 +25322,7 @@ async function updateLinearIssue(input, opts) {
25281
25322
  }
25282
25323
  const addRelations = input.relations?.length ? input.relations : void 0;
25283
25324
  const removeRelations = input.removeRelations?.length ? input.removeRelations : void 0;
25284
- const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
25325
+ const needsIssue = Boolean(input.state?.trim()) || input.cycle !== void 0 || input.labels !== void 0 || Boolean(addRelations) || Boolean(removeRelations);
25285
25326
  const existing = needsIssue ? await getLinearIssue(issueId, opts) : void 0;
25286
25327
  if (input.state?.trim()) {
25287
25328
  const { teams } = await listLinearTeams(opts);
@@ -25316,7 +25357,10 @@ async function updateLinearIssue(input, opts) {
25316
25357
  mutationInput.priority = normalizePriority(input.priority);
25317
25358
  }
25318
25359
  if (input.labels !== void 0) {
25319
- mutationInput.labelIds = await resolveLinearLabelIds(input.labels, opts);
25360
+ mutationInput.labelIds = await resolveLinearLabelIds(input.labels, {
25361
+ ...opts,
25362
+ teamId: existing?.team?.id
25363
+ });
25320
25364
  }
25321
25365
  if (input.project !== void 0) {
25322
25366
  mutationInput.projectId = await resolveLinearProjectId(input.project, opts);
@@ -25622,7 +25666,7 @@ function parseProjectTitles(raw) {
25622
25666
  }
25623
25667
  async function listGitHubIssueProjects(number, cwd, repoArgs) {
25624
25668
  const result = await gh(
25625
- ["issue", "view", String(number), ...repoArgs, "--json", "projectItems,projects"],
25669
+ ["issue", "view", String(number), ...repoArgs, "--json", "projectItems"],
25626
25670
  cwd,
25627
25671
  { reject: false }
25628
25672
  );
@@ -28956,7 +29000,7 @@ async function startMcpServer() {
28956
29000
  );
28957
29001
  server.tool(
28958
29002
  "send_to_thread",
28959
- 'Queue a prompt on a worktree thread chat (runs under concurrency cap). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not force_stop to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that stops the child mid-thought. Call wait_for_turn again instead.',
29003
+ 'Steer a prompt on a worktree thread chat (Settings \u2192 Follow-up, default steer: interrupt and start now, skip the inbox). Use after create_thread to start or continue a conversation. For commit/push/PR, prefer ask_git (canonical desktop-button phrases). Send "Merge PR." / ask_git merge only when the user explicitly asked to merge. force_stop=true kills the in-flight turn and clears the queue before this prompt \u2014 only when the current request is wrong and must be replaced. Do not send_to_thread to check in, resume after a halt notice, or because wait_for_turn returned stillRunning; that interrupts the child mid-thought. Call wait_for_turn again instead.',
28960
29004
  {
28961
29005
  ref: import_zod9.z.string(),
28962
29006
  prompt: import_zod9.z.string(),
@@ -28969,7 +29013,9 @@ async function startMcpServer() {
28969
29013
  orch.stop(ref, { clearQueue: true, notifyParent: false });
28970
29014
  }
28971
29015
  }
28972
- const thread = await orch.send(ref, prompt);
29016
+ const thread = await orch.send(ref, prompt, {
29017
+ followUp: resolveOrchChildFollowUp()
29018
+ });
28973
29019
  return mcpJson({
28974
29020
  id: thread.id,
28975
29021
  status: thread.status,
@@ -28980,7 +29026,7 @@ async function startMcpServer() {
28980
29026
  );
28981
29027
  server.tool(
28982
29028
  "wait_for_turn",
28983
- "Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send a check-in prompt, force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
29029
+ "Wait until the thread finishes its current/queued turn, or return early with a live progress snapshot. MCP clients often kill tools around 60s, so this returns within 45s even while the child is still working. stillRunning is the source of truth \u2014 if false, the child is not working (do not say it is waiting for a gate). If stillRunning is true, progress is tools/thinking (or \u201Cqueued, waiting for a concurrency slot\u201D if it has not started). Call wait_for_turn again. Do not send_to_thread a check-in (that steers / interrupts), force_stop, or assume a hang. On status error, lastError/text is the failure. On status stopped or broken, the child did not finish \u2014 resume with send_to_thread or tell the user; do not treat that as success. When finished, usage is the last agent turn\u2019s tokens + costUsd (when the provider reported cost).",
28984
29030
  {
28985
29031
  ref: import_zod9.z.string(),
28986
29032
  timeoutMs: import_zod9.z.number().optional()
@@ -29137,7 +29183,7 @@ async function startMcpServer() {
29137
29183
  );
29138
29184
  server.tool(
29139
29185
  "ask_git",
29140
- "Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, queues the worktree agent to commit; then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=ready-for-review and action=merge only when the user explicitly asked (or clicked the desktop button). Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
29186
+ "Commit & push, open a draft PR, mark ready for review, resolve conflicts, or merge \u2014 same actions as the desktop git buttons. When the worktree is clean, Sideboard pushes / opens the PR itself (HTTPS via `gh` even when origin is SSH / Settings \u2192 Git is SSH). When dirty, steers the worktree agent to commit (Settings \u2192 Follow-up, default interrupt now); then wait_for_turn (loop while stillRunning). Do not start a checks loop on a plain push \u2014 only if the user gave a goal (Greptile 5/5, CI green). Pass a worktree thread ref (not the orchestrator). action=ready-for-review and action=merge only when the user explicitly asked (or clicked the desktop button). Do not run git or gh from the orchestration cwd. If this tool errors that the GraphQL/PR body is too long, the branch is already pushed \u2014 have the worktree agent retry `gh pr create --body-file` with a short description (GitHub limit 65,536 characters). Do not invent SSH/auth failures from that error.",
29141
29187
  {
29142
29188
  ref: import_zod9.z.string().describe("Worktree thread id/ref"),
29143
29189
  action: import_zod9.z.enum(AGENT_GIT_ACTIONS).describe(
@@ -32430,6 +32476,7 @@ init_outbound_watch();
32430
32476
  resolveLoginCommand,
32431
32477
  resolveNewOrchestratorOptions,
32432
32478
  resolveNewThreadOptions,
32479
+ resolveOrchChildFollowUp,
32433
32480
  resolveOrchestratorDefaults,
32434
32481
  resolvePlanMarkdown,
32435
32482
  resolvePrSelector,