@sideboard-ai/core 0.1.297 → 0.1.298

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 (37) hide show
  1. package/dist/{agents-ICHYDSCD.js → agents-GHZFY65E.js} +5 -5
  2. package/dist/{agents-DZTPUKVF.js → agents-XL67HSZH.js} +5 -5
  3. package/dist/{chunk-QT36F4TD.js → chunk-2POLTCSC.js} +326 -25
  4. package/dist/{chunk-VXNZG4J6.js → chunk-3IXGI2FP.js} +1 -1
  5. package/dist/{chunk-67BWWLEB.js → chunk-4FWMUMXG.js} +5 -5
  6. package/dist/{chunk-WQREAX35.js → chunk-5FMQU2RU.js} +9 -5
  7. package/dist/{chunk-ED4ZXQVO.js → chunk-5XQ43YZU.js} +2 -1
  8. package/dist/{chunk-JWXJXEA3.js → chunk-BIMHIHX3.js} +1 -1
  9. package/dist/{chunk-Q3DPZ4DE.js → chunk-F36QRDM4.js} +2 -1
  10. package/dist/{chunk-6GTABVNG.js → chunk-IL77XODJ.js} +6 -4
  11. package/dist/{chunk-ZXWRNA4G.js → chunk-JM5P36PM.js} +5 -5
  12. package/dist/{chunk-WZLV4WNS.js → chunk-K5EACGG2.js} +11 -0
  13. package/dist/{chunk-BGEECLKH.js → chunk-KMYCNSSI.js} +9 -5
  14. package/dist/{chunk-W2A63ZOK.js → chunk-KRGQWQME.js} +329 -26
  15. package/dist/{chunk-2O3ICR77.js → chunk-RQMLJZ2V.js} +6 -4
  16. package/dist/{conductor-ZXDIA6OF.js → conductor-HUITLA2M.js} +5 -5
  17. package/dist/{conductor-HJFDYIZD.js → conductor-NGIEDMAB.js} +5 -5
  18. package/dist/{coordinator-prompt-L3V2CMWX.js → coordinator-prompt-52T5A4SU.js} +3 -3
  19. package/dist/{coordinator-prompt-ILHSVPOG.js → coordinator-prompt-JUN3IITF.js} +3 -3
  20. package/dist/{global-workspace-47G453ZU.js → global-workspace-VVUIFQ72.js} +3 -3
  21. package/dist/{global-workspace-NMRUGGFF.js → global-workspace-Z5YRL67Y.js} +3 -3
  22. package/dist/index.cjs +793 -337
  23. package/dist/index.d.cts +16 -9
  24. package/dist/index.d.ts +16 -9
  25. package/dist/index.js +343 -228
  26. package/dist/mcp/run-stdio.cjs +739 -302
  27. package/dist/mcp/run-stdio.js +323 -217
  28. package/dist/{orchestrator-MR7TCIPP.js → orchestrator-JY4ZETFX.js} +7 -7
  29. package/dist/{orchestrator-ZQU62CES.js → orchestrator-S7TKI6DR.js} +7 -7
  30. package/dist/{thread-store-H6D6MDUM.js → thread-store-5XXHSWMN.js} +1 -1
  31. package/dist/{thread-store-SADLLKRE.js → thread-store-WXLXKDVN.js} +1 -1
  32. package/dist/{workspaces-PGY4UWZ3.js → workspaces-7FVNGUBV.js} +3 -3
  33. package/dist/{workspaces-WGZPRQJX.js → workspaces-OSF56FHS.js} +3 -3
  34. package/dist/{worktree-JZXDAKQF.js → worktree-6G5X4ABY.js} +2 -2
  35. package/dist/{worktree-3MF5J5XZ.js → worktree-LFSBIUCN.js} +2 -2
  36. package/package.json +1 -1
  37. /package/dist/{chunk-TVN4TDFB.js → chunk-HTL4FBTP.js} +0 -0
@@ -14,7 +14,7 @@ import {
14
14
  parseSessionQuotaResetAt,
15
15
  planModeTurnInstruction,
16
16
  resolveQuotaFallbackAgent
17
- } from "./chunk-6GTABVNG.js";
17
+ } from "./chunk-IL77XODJ.js";
18
18
  import {
19
19
  REVIEW_TAB_TITLE,
20
20
  applyWorktreePkgCacheEnv,
@@ -53,7 +53,7 @@ import {
53
53
  worktreeDevProcessKey,
54
54
  worktreeRunProcessKey,
55
55
  worktreeSetupProcessKey
56
- } from "./chunk-67BWWLEB.js";
56
+ } from "./chunk-4FWMUMXG.js";
57
57
  import {
58
58
  applyAgentEvent,
59
59
  clipAgentEventForPaint,
@@ -68,7 +68,7 @@ import {
68
68
  partsToAssistantText,
69
69
  stripBrightsyNdjsonNoise,
70
70
  toolDescription
71
- } from "./chunk-Q3DPZ4DE.js";
71
+ } from "./chunk-F36QRDM4.js";
72
72
  import {
73
73
  titleFromPrompt
74
74
  } from "./chunk-7H655NEW.js";
@@ -100,7 +100,7 @@ import {
100
100
  stageAbsolutePathsAsAttachments,
101
101
  stageBuffersAsAttachments,
102
102
  syncWorkspacesFromThreads
103
- } from "./chunk-BGEECLKH.js";
103
+ } from "./chunk-KMYCNSSI.js";
104
104
  import {
105
105
  addPrStackLayer,
106
106
  allocateTeamSlug,
@@ -142,7 +142,7 @@ import {
142
142
  resolveRepoRoot,
143
143
  switchWorktreeBranch,
144
144
  withRepoGitLock
145
- } from "./chunk-JWXJXEA3.js";
145
+ } from "./chunk-BIMHIHX3.js";
146
146
  import {
147
147
  agentNicknameFromWorktreePath,
148
148
  appendMessage,
@@ -166,7 +166,7 @@ import {
166
166
  worktreeNameFromPath,
167
167
  worktreeSlugForTicket,
168
168
  writeThread
169
- } from "./chunk-WZLV4WNS.js";
169
+ } from "./chunk-K5EACGG2.js";
170
170
  import {
171
171
  createAgentStreamCoalescer
172
172
  } from "./chunk-AXQ4ZWHK.js";
@@ -451,9 +451,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
451
451
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
452
452
  );
453
453
  }
454
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-47G453ZU.js");
454
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-VVUIFQ72.js");
455
455
  if (isGlobalThread2(thread)) {
456
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-ILHSVPOG.js");
456
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-JUN3IITF.js");
457
457
  ensureGlobalCoordinatorCwd2(
458
458
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
459
459
  );
@@ -1607,6 +1607,23 @@ function denyPendingToolPermissions(threadId) {
1607
1607
  if (last) clearPrompt(threadId, last.id);
1608
1608
  }
1609
1609
 
1610
+ // src/threads/connected-orchestrator.ts
1611
+ function connectedOrchestrator(thread, find) {
1612
+ if (isOrchestratorThread(thread)) return null;
1613
+ const seen = /* @__PURE__ */ new Set();
1614
+ let current = thread;
1615
+ for (let hop = 0; hop < 6 && current; hop++) {
1616
+ const parentId = current.parentThreadId?.trim();
1617
+ if (!parentId || seen.has(parentId)) return null;
1618
+ seen.add(parentId);
1619
+ const parent = find(parentId);
1620
+ if (!parent) return null;
1621
+ if (isOrchestratorThread(parent)) return parent;
1622
+ current = parent;
1623
+ }
1624
+ return null;
1625
+ }
1626
+
1610
1627
  // src/orchestrator/notify-orchestrator.ts
1611
1628
  var MAX_NOTIFY_ORCHESTRATOR_MESSAGE_CHARS = 1500;
1612
1629
  var inputRequiredNotified = /* @__PURE__ */ new Set();
@@ -1659,22 +1676,25 @@ function resolveNotifyCallerThread(opts) {
1659
1676
  return running;
1660
1677
  }
1661
1678
  function skipReason(opts) {
1662
- if (!opts.child.parentThreadId) {
1679
+ const parentId = opts.child.parentThreadId?.trim();
1680
+ if (!parentId) {
1663
1681
  return "This chat has no orchestrator parent. notify_orchestrator is for worktree children of a Global chat.";
1664
1682
  }
1665
- if (!opts.parent) {
1666
- return "Parent orchestration chat was not found.";
1667
- }
1668
- if (opts.parent.status === "archived") {
1683
+ if (opts.parent?.status === "archived") {
1669
1684
  return "Parent orchestration chat is archived.";
1670
1685
  }
1686
+ if (!opts.parent) {
1687
+ const immediate = readThread(parentId);
1688
+ if (!immediate) return "Parent orchestration chat was not found.";
1689
+ return "Parent is not a Global orchestration chat.";
1690
+ }
1671
1691
  if (!isOrchestratorThread(opts.parent)) {
1672
1692
  return "Parent is not a Global orchestration chat.";
1673
1693
  }
1674
1694
  return "Cannot notify orchestrator.";
1675
1695
  }
1676
1696
  async function notifyOrchestrator(input) {
1677
- const parent = input.child.parentThreadId ? readThread(input.child.parentThreadId) : null;
1697
+ const parent = connectedOrchestrator(input.child, (id) => readThread(id));
1678
1698
  if (!shouldNotifyOrchestrator({ child: input.child, parent })) {
1679
1699
  return { ok: false, error: skipReason({ child: input.child, parent }) };
1680
1700
  }
@@ -2401,9 +2421,9 @@ var BOARD_PAGE_SIZE = 40;
2401
2421
  function tokenizeQuery(query) {
2402
2422
  return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
2403
2423
  }
2404
- function haystackMatches(haystack, tokens) {
2424
+ function haystackMatches(haystack2, tokens) {
2405
2425
  if (tokens.length === 0) return true;
2406
- const h = haystack.toLowerCase();
2426
+ const h = haystack2.toLowerCase();
2407
2427
  return tokens.every((token) => h.includes(token));
2408
2428
  }
2409
2429
  function prAuthorLogin(pr) {
@@ -2596,7 +2616,7 @@ function assembleHomeBoard(input) {
2596
2616
  }
2597
2617
  return { columns, hidden, totals };
2598
2618
  }
2599
- var HOME_BOARD_AGENT_HINT = "Home is a Kanban of workspaces (one card per checkout; sibling chats on a card are separate agents). Do not create a second workspace for a ticket, PR, or named branch that already has a live checkout \u2014 create_workspace / start_board_card return that checkout (alreadyStarted) and its chats. Add another agent with fork_chat. Creating from the default branch still opens a new isolated workspace. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. ownership=mine is PRs you authored (or WIP with no PR); ownership=reviewing is someone else's PR (or a review-requested checkout). Viewer login comes from gh, not a setting. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. blockedReason means an agent on that card is waiting on a person (the question, plan approval, or a reported block) \u2014 read it and do not send_to_chat a check-in. Orchestration chats stay in the sidebar. Do not invent status.";
2619
+ var HOME_BOARD_AGENT_HINT = "Home is a Kanban of workspaces (one card per checkout; sibling chats on a card are separate agents). Do not create a second workspace for a ticket, PR, or named branch that already has a live checkout \u2014 create_workspace / start_board_card return that checkout (alreadyStarted) and its chats. Add another agent with fork_chat. Creating from the default branch still opens a new isolated workspace. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. ownership=mine is PRs you authored (or WIP with no PR); ownership=reviewing is someone else's PR (or a review-requested checkout). Viewer login comes from gh, not a setting. Archive removes the card to Settings \u2192 History (list_archive to browse, restore_workspace to bring it back). Queued/running are activity on the card, not columns. blockedReason means an agent on that card is waiting on a person (the question, plan approval, or a reported block) \u2014 read it and do not send_to_chat a check-in. Orchestration chats stay in the sidebar. Do not invent status.";
2600
2620
 
2601
2621
  // src/threads/workspace-tags.ts
2602
2622
  function workspaceTagTargetRef(opts) {
@@ -2872,7 +2892,7 @@ async function createThread(input, _onSetupLine) {
2872
2892
  return readThread(thread.id) ?? thread;
2873
2893
  }
2874
2894
  async function listLinearIssues(agent, repoPath) {
2875
- const { getAdapter: getAdapter2 } = await import("./agents-ICHYDSCD.js");
2895
+ const { getAdapter: getAdapter2 } = await import("./agents-GHZFY65E.js");
2876
2896
  await requireAgent(agent, { requireLinear: true });
2877
2897
  const adapter = getAdapter2(agent);
2878
2898
  if (!adapter.listLinearIssues) {
@@ -2904,6 +2924,271 @@ function shouldRemoveWorktreeOnTeardown(thread) {
2904
2924
  return !isCowboyThread(thread) && !isPrimaryCheckoutThread(thread);
2905
2925
  }
2906
2926
 
2927
+ // src/archive/fleet-archive.ts
2928
+ import { basename as basename2 } from "path";
2929
+ var DEFAULT_LIMIT = 40;
2930
+ var MAX_LIMIT = 250;
2931
+ function oneLine(value) {
2932
+ return value.replace(/\s+/g, " ").trim();
2933
+ }
2934
+ function stampOf(thread) {
2935
+ return thread.archivedAt?.trim() || thread.updatedAt || thread.createdAt || "";
2936
+ }
2937
+ function repoLabel(thread) {
2938
+ if (isOrchestratorThread(thread)) return "Orchestration";
2939
+ const path = thread.repoPath?.trim() ?? "";
2940
+ return path && basename2(path) || path || "project";
2941
+ }
2942
+ function toAgent(thread, flags) {
2943
+ const prUrl = thread.prUrl?.trim();
2944
+ return {
2945
+ id: thread.id,
2946
+ title: thread.title?.trim() || "Untitled",
2947
+ agent: thread.agent,
2948
+ repo: repoLabel(thread),
2949
+ branch: thread.branchName ?? "",
2950
+ sourceType: thread.sourceType,
2951
+ sourceRef: thread.sourceRef,
2952
+ archivedAt: stampOf(thread),
2953
+ ...prUrl ? { prUrl } : {},
2954
+ ...flags?.workspaceLive ? { workspaceLive: true } : {},
2955
+ ...flags?.workspaceArchived ? { workspaceArchived: true } : {}
2956
+ };
2957
+ }
2958
+ function checkoutKey(thread) {
2959
+ return thread.worktreePath?.trim() ? normalizeWorktreePath(thread.worktreePath) : "";
2960
+ }
2961
+ function liveCheckoutKeys(threads) {
2962
+ const keys = /* @__PURE__ */ new Set();
2963
+ for (const thread of threads) {
2964
+ if (thread.status === "archived" || isOrchestratorThread(thread)) continue;
2965
+ const key = checkoutKey(thread);
2966
+ if (key) keys.add(key);
2967
+ }
2968
+ return keys;
2969
+ }
2970
+ function workspaceFrom(agents) {
2971
+ const ordered = [...agents].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
2972
+ const primary = ordered[0];
2973
+ const rows = ordered.map((thread) => toAgent(thread));
2974
+ const archivedAt = rows.reduce(
2975
+ (latest, row) => row.archivedAt > latest ? row.archivedAt : latest,
2976
+ ""
2977
+ );
2978
+ const prUrl = ordered.map((thread) => thread.prUrl?.trim()).find(Boolean);
2979
+ return {
2980
+ id: primary.id,
2981
+ title: primary.title?.trim() || "Untitled",
2982
+ repo: repoLabel(primary),
2983
+ branch: primary.branchName ?? "",
2984
+ sourceType: primary.sourceType,
2985
+ sourceRef: primary.sourceRef,
2986
+ archivedAt,
2987
+ ...prUrl ? { prUrl } : {},
2988
+ ...ordered.some((thread) => thread.cowboy) ? { cowboy: true } : {},
2989
+ agents: rows
2990
+ };
2991
+ }
2992
+ function haystack(parts) {
2993
+ return parts.filter(Boolean).join(" ").toLowerCase();
2994
+ }
2995
+ function agentHay(agent) {
2996
+ return haystack([
2997
+ agent.id,
2998
+ agent.title,
2999
+ agent.agent,
3000
+ agent.repo,
3001
+ agent.branch,
3002
+ agent.sourceType,
3003
+ agent.sourceRef,
3004
+ agent.prUrl
3005
+ ]);
3006
+ }
3007
+ function workspaceMatches(workspace, query) {
3008
+ if (!query) return true;
3009
+ const own = haystack([
3010
+ workspace.id,
3011
+ workspace.title,
3012
+ workspace.repo,
3013
+ workspace.branch,
3014
+ workspace.sourceType,
3015
+ workspace.sourceRef,
3016
+ workspace.prUrl
3017
+ ]);
3018
+ if (own.includes(query)) return true;
3019
+ return workspace.agents.some((agent) => agentHay(agent).includes(query));
3020
+ }
3021
+ function clampLimit(limit) {
3022
+ if (limit == null || !Number.isFinite(limit)) return DEFAULT_LIMIT;
3023
+ return Math.min(MAX_LIMIT, Math.max(1, Math.floor(limit)));
3024
+ }
3025
+ function listFleetArchive(threads, opts) {
3026
+ const query = opts?.query?.trim().toLowerCase() ?? "";
3027
+ const kind = opts?.kind ?? "all";
3028
+ const limit = clampLimit(opts?.limit);
3029
+ const liveKeys = liveCheckoutKeys(threads);
3030
+ const archived = threads.filter((thread) => thread.status === "archived");
3031
+ const groups = /* @__PURE__ */ new Map();
3032
+ const loose = [];
3033
+ for (const thread of archived) {
3034
+ const key = checkoutKey(thread);
3035
+ if (!key || isOrchestratorThread(thread) || liveKeys.has(key)) {
3036
+ loose.push(thread);
3037
+ continue;
3038
+ }
3039
+ const group = groups.get(key) ?? [];
3040
+ group.push(thread);
3041
+ groups.set(key, group);
3042
+ }
3043
+ const rows = [];
3044
+ if (kind !== "agent") {
3045
+ for (const group of groups.values()) {
3046
+ const workspace = workspaceFrom(group);
3047
+ if (!workspaceMatches(workspace, query)) continue;
3048
+ rows.push({ kind: "workspace", stamp: workspace.archivedAt, workspace });
3049
+ }
3050
+ }
3051
+ if (kind !== "workspace") {
3052
+ const pool = kind === "agent" ? archived : loose;
3053
+ for (const thread of pool) {
3054
+ const key = checkoutKey(thread);
3055
+ const orchestration = isOrchestratorThread(thread);
3056
+ const agent = toAgent(thread, {
3057
+ workspaceLive: Boolean(key) && !orchestration && liveKeys.has(key),
3058
+ workspaceArchived: Boolean(key) && !orchestration && !liveKeys.has(key)
3059
+ });
3060
+ if (query && !agentHay(agent).includes(query)) continue;
3061
+ rows.push({ kind: "agent", stamp: agent.archivedAt, agent });
3062
+ }
3063
+ }
3064
+ rows.sort((a, b) => {
3065
+ if (a.stamp !== b.stamp) return a.stamp < b.stamp ? 1 : -1;
3066
+ const idA = a.kind === "workspace" ? a.workspace.id : a.agent.id;
3067
+ const idB = b.kind === "workspace" ? b.workspace.id : b.agent.id;
3068
+ return idA.localeCompare(idB);
3069
+ });
3070
+ const page = rows.slice(0, limit);
3071
+ return {
3072
+ rows: page,
3073
+ shown: page.length,
3074
+ hidden: Math.max(0, rows.length - page.length),
3075
+ total: rows.length,
3076
+ query
3077
+ };
3078
+ }
3079
+ function archivedAgentsOnCheckout(threads, worktreePath) {
3080
+ const key = worktreePath.trim() ? normalizeWorktreePath(worktreePath) : "";
3081
+ if (!key) return [];
3082
+ return threads.filter(
3083
+ (thread) => thread.status === "archived" && !isOrchestratorThread(thread) && Boolean(thread.worktreePath?.trim()) && normalizeWorktreePath(thread.worktreePath) === key
3084
+ ).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
3085
+ }
3086
+ function formatWorkspaceLine(workspace) {
3087
+ const bits = [
3088
+ workspace.id.slice(0, 8),
3089
+ "workspace",
3090
+ workspace.repo,
3091
+ workspace.branch ? `branch:${workspace.branch}` : "",
3092
+ workspace.sourceType && workspace.sourceRef ? `${workspace.sourceType}:${workspace.sourceRef}` : "",
3093
+ `agents:${workspace.agents.length}`,
3094
+ workspace.cowboy ? "cowboy" : "",
3095
+ workspace.prUrl ?? "",
3096
+ workspace.archivedAt ? `archived:${workspace.archivedAt}` : "",
3097
+ oneLine(workspace.title)
3098
+ ].filter(Boolean);
3099
+ return bits.join(" ");
3100
+ }
3101
+ function formatAgentLine(agent) {
3102
+ const bits = [
3103
+ agent.id.slice(0, 8),
3104
+ "agent",
3105
+ agent.repo,
3106
+ agent.agent,
3107
+ agent.branch ? `branch:${agent.branch}` : "",
3108
+ agent.sourceType && agent.sourceRef ? `${agent.sourceType}:${agent.sourceRef}` : "",
3109
+ agent.workspaceLive ? "workspace-live" : "",
3110
+ agent.workspaceArchived ? "workspace-archived" : "",
3111
+ agent.prUrl ?? "",
3112
+ agent.archivedAt ? `archived:${agent.archivedAt}` : "",
3113
+ oneLine(agent.title),
3114
+ `sideboard://chat/${agent.id}`
3115
+ ].filter(Boolean);
3116
+ return bits.join(" ");
3117
+ }
3118
+ function formatFleetArchive(view) {
3119
+ if (view.total === 0) {
3120
+ return view.query ? "(no archive matches)" : "(archive empty)";
3121
+ }
3122
+ const lines = [
3123
+ `${view.shown} shown, ${view.hidden} hidden. restore_workspace <id> brings that checkout and every archived agent back. restore_chat <id> brings one agent back.`
3124
+ ];
3125
+ for (const row of view.rows) {
3126
+ if (row.kind === "workspace") {
3127
+ lines.push(formatWorkspaceLine(row.workspace));
3128
+ for (const agent of row.workspace.agents) {
3129
+ lines.push(
3130
+ ` ${agent.id.slice(0, 8)} ${agent.agent} ${oneLine(agent.title)} sideboard://chat/${agent.id}`
3131
+ );
3132
+ }
3133
+ continue;
3134
+ }
3135
+ lines.push(formatAgentLine(row.agent));
3136
+ }
3137
+ return lines.join("\n");
3138
+ }
3139
+
3140
+ // src/orchestrator/workspace-archive.ts
3141
+ function requireHostThread(host, ref) {
3142
+ const thread = host.getThread(ref);
3143
+ if (!thread) throw new Error(`Thread not found: ${ref}`);
3144
+ return thread;
3145
+ }
3146
+ async function archiveWorkspaceAgents(host, threadRef) {
3147
+ const thread = requireHostThread(host, threadRef);
3148
+ if (isOrchestratorThread(thread)) {
3149
+ throw new Error("Orchestration chats are agents, not workspaces. Use archive_chat.");
3150
+ }
3151
+ if (!thread.worktreePath?.trim()) {
3152
+ throw new Error("Chat has no workspace checkout. Use archive_chat.");
3153
+ }
3154
+ const chats = threadsSharingWorktree(thread.worktreePath);
3155
+ if (chats.length === 0) {
3156
+ throw new Error(
3157
+ "That workspace is already archived. Use list_archive, then restore_workspace to bring it back."
3158
+ );
3159
+ }
3160
+ const archived = [];
3161
+ for (const chat of chats) {
3162
+ archived.push(await host.archive(chat.id));
3163
+ }
3164
+ return archived;
3165
+ }
3166
+ async function restoreWorkspaceAgents(host, threadRef) {
3167
+ const thread = requireHostThread(host, threadRef);
3168
+ if (isOrchestratorThread(thread)) {
3169
+ throw new Error("Orchestration chats are agents, not workspaces. Use restore_chat.");
3170
+ }
3171
+ if (!thread.worktreePath?.trim()) {
3172
+ throw new Error("Chat has no workspace checkout. Use restore_chat.");
3173
+ }
3174
+ const targets = archivedAgentsOnCheckout(
3175
+ listThreads({ includeArchived: true }),
3176
+ thread.worktreePath
3177
+ );
3178
+ const restored = [];
3179
+ for (const chat of targets) {
3180
+ const latest = readThread(chat.id);
3181
+ if (!latest || latest.status !== "archived") continue;
3182
+ restored.push(await host.restore(latest.id));
3183
+ }
3184
+ if (restored.length === 0) {
3185
+ throw new Error(
3186
+ "No archived agents on this workspace. list_archive shows what can be restored."
3187
+ );
3188
+ }
3189
+ return restored;
3190
+ }
3191
+
2907
3192
  // src/util/line-coalescer.ts
2908
3193
  function createLineCoalescer(onChunk, opts) {
2909
3194
  const delayMs = opts?.delayMs ?? 50;
@@ -3383,7 +3668,7 @@ async function adoptThread(input) {
3383
3668
  messages: input.messages ?? []
3384
3669
  });
3385
3670
  writeThread(thread);
3386
- const { addWorkspace: addWorkspace2 } = await import("./workspaces-WGZPRQJX.js");
3671
+ const { addWorkspace: addWorkspace2 } = await import("./workspaces-OSF56FHS.js");
3387
3672
  await addWorkspace2(repoPath);
3388
3673
  const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-RXZPTCNH.js");
3389
3674
  await ensureWorktreeSideboardIgnored(input.worktreePath);
@@ -5435,6 +5720,16 @@ function formatWorktreeDirective(thread, opts) {
5435
5720
  lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
5436
5721
  return lines.join("\n");
5437
5722
  }
5723
+ function formatConnectedOrchestratorReminder(parent) {
5724
+ if (!parent) return null;
5725
+ const title = parent.title?.trim() || "Orchestration";
5726
+ const archived = parent.status === "archived" ? " This orchestrator is archived." : "";
5727
+ return `Connected orchestrator: "${title}" (${parent.agent}, ${parent.status}). Open [${title}](sideboard://chat/${parent.id}). notify_orchestrator wakes that chat. You are not the orchestrator.${archived}`;
5728
+ }
5729
+ function connectedOrchestratorTurnReminder(thread, find) {
5730
+ if (thread.agent === "brightsy" || isOrchestratorThread(thread)) return null;
5731
+ return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
5732
+ }
5438
5733
  function formatWorktreeReminder() {
5439
5734
  return "Sideboard workspace: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push. Schedules: create_schedule (at / every / cron; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
5440
5735
  }
@@ -6302,7 +6597,7 @@ function formatScheduledPrompt(name, prompt) {
6302
6597
  ${prompt}`;
6303
6598
  }
6304
6599
  async function defaultDeps() {
6305
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-ZQU62CES.js");
6600
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-S7TKI6DR.js");
6306
6601
  const orch = getOrchestrator2();
6307
6602
  return {
6308
6603
  findThread: (id) => findThreadByRef(id),
@@ -7374,6 +7669,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
7374
7669
  );
7375
7670
  const turnReminders = [
7376
7671
  worktreeReminder,
7672
+ connectedOrchestratorTurnReminder(thread, (id) => readThread(id)),
7377
7673
  optionalServicesReminder,
7378
7674
  issueToolsReminder,
7379
7675
  reviewWriteGateReminder,
@@ -8971,14 +9267,16 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
8971
9267
  const thread = this.requireThread(threadRef);
8972
9268
  return threadsSharingWorktree(thread.worktreePath);
8973
9269
  }
8974
- /**
8975
- * Last-tab teardown must see siblings already archived. Serialize per
8976
- * worktree so parallel archive/purge of sibling tabs still removes once.
8977
- */
8978
9270
  enqueueWorktreeTeardown(thread, fn) {
8979
9271
  const key = isGlobalThread(thread) ? `archive:global:${thread.id}` : `archive:wt:${normalizeWorktreePath(thread.worktreePath)}`;
8980
9272
  return enqueueByKey(key, fn);
8981
9273
  }
9274
+ archiveWorkspace(threadRef) {
9275
+ return archiveWorkspaceAgents(this, threadRef);
9276
+ }
9277
+ restoreWorkspace(threadRef) {
9278
+ return restoreWorkspaceAgents(this, threadRef);
9279
+ }
8982
9280
  async archive(threadRef) {
8983
9281
  const thread = this.requireThread(threadRef);
8984
9282
  return this.enqueueWorktreeTeardown(thread, () => this.archiveUnlocked(threadRef));
@@ -9174,7 +9472,7 @@ async function startOrchestration(opts) {
9174
9472
  sourceRef: "default",
9175
9473
  ...createOpts
9176
9474
  }).catch(async () => {
9177
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-3MF5J5XZ.js");
9475
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-LFSBIUCN.js");
9178
9476
  const repo = await resolveRepoRoot2(repoPath);
9179
9477
  const def = await resolveDefaultBranch2(repo);
9180
9478
  return orch.createThread({
@@ -9184,7 +9482,7 @@ async function startOrchestration(opts) {
9184
9482
  repoPath: repo
9185
9483
  });
9186
9484
  });
9187
- const { updateThread: upd } = await import("./thread-store-SADLLKRE.js");
9485
+ const { updateThread: upd } = await import("./thread-store-WXLXKDVN.js");
9188
9486
  const updated = upd(thread.id, {
9189
9487
  sourceType: "orchestration",
9190
9488
  sourceRef: goal
@@ -9273,6 +9571,7 @@ export {
9273
9571
  shouldRunHistoryCleanup,
9274
9572
  applyThreadIntoMain,
9275
9573
  cloneRepoIntoSideboard,
9574
+ connectedOrchestrator,
9276
9575
  formatAskUserNotifyMessage,
9277
9576
  formatNotifyOrchestratorPrompt,
9278
9577
  shouldNotifyOrchestrator,
@@ -9296,6 +9595,8 @@ export {
9296
9595
  isCowboyThread,
9297
9596
  isPrimaryCheckoutThread,
9298
9597
  shouldRemoveWorktreeOnTeardown,
9598
+ listFleetArchive,
9599
+ formatFleetArchive,
9299
9600
  readTurnLiveParts,
9300
9601
  readTurnLive,
9301
9602
  shouldStampSetupLastError,
@@ -9351,6 +9652,8 @@ export {
9351
9652
  localhostPreviewUrl,
9352
9653
  formatDevAccessHint,
9353
9654
  formatWorktreeDirective,
9655
+ formatConnectedOrchestratorReminder,
9656
+ connectedOrchestratorTurnReminder,
9354
9657
  formatWorktreeReminder,
9355
9658
  mentionsPrGoal,
9356
9659
  issueTicketFromThread,
@@ -21,16 +21,16 @@ import {
21
21
  looksLikeSkillBody,
22
22
  skillCommandFromBody,
23
23
  withEventParentId
24
- } from "./chunk-ED4ZXQVO.js";
24
+ } from "./chunk-5XQ43YZU.js";
25
25
  import {
26
26
  isOrchestratorThread
27
- } from "./chunk-WQREAX35.js";
27
+ } from "./chunk-5FMQU2RU.js";
28
28
  import {
29
29
  codexUnattendedGitConfigArgs,
30
30
  mergeAgentGitAuthEnv,
31
31
  resolveAgentGitAuthEnv,
32
32
  resolveCodexGitWritableRoots
33
- } from "./chunk-VXNZG4J6.js";
33
+ } from "./chunk-3IXGI2FP.js";
34
34
  import {
35
35
  npmGlobalNodeModules,
36
36
  run
@@ -559,6 +559,7 @@ var WORKTREE_MCP_TOOLS = [
559
559
  "run_dev_script",
560
560
  "stop_dev_script",
561
561
  "get_run_log",
562
+ "get_orchestrator",
562
563
  "notify_orchestrator",
563
564
  "set_workspace_tags",
564
565
  "get_viewer_context",
@@ -963,6 +964,7 @@ var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
963
964
  "mcp__sideboard__run_dev_script",
964
965
  "mcp__sideboard__stop_dev_script",
965
966
  "mcp__sideboard__get_run_log",
967
+ "mcp__sideboard__get_orchestrator",
966
968
  "mcp__sideboard__notify_orchestrator",
967
969
  "mcp__sideboard__set_workspace_tags",
968
970
  "mcp__sideboard__get_viewer_context",
@@ -2018,7 +2020,7 @@ var claudeAdapter = {
2018
2020
  );
2019
2021
  }
2020
2022
  const mode = permissionMode(thread);
2021
- const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-NMRUGGFF.js");
2023
+ const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-Z5YRL67Y.js");
2022
2024
  const isOrchestrator = isOrchestratorThread2(thread);
2023
2025
  const rpc = worktreeAgentRpc(isOrchestrator);
2024
2026
  const injectedServers = await buildInjectedMcpServers({
@@ -31,11 +31,11 @@ import {
31
31
  tryReservePort,
32
32
  tryReservePorts,
33
33
  worktreeRunPortsPath
34
- } from "./chunk-67BWWLEB.js";
35
- import "./chunk-Q3DPZ4DE.js";
36
- import "./chunk-BGEECLKH.js";
37
- import "./chunk-JWXJXEA3.js";
38
- import "./chunk-WZLV4WNS.js";
34
+ } from "./chunk-4FWMUMXG.js";
35
+ import "./chunk-F36QRDM4.js";
36
+ import "./chunk-KMYCNSSI.js";
37
+ import "./chunk-BIMHIHX3.js";
38
+ import "./chunk-K5EACGG2.js";
39
39
  import "./chunk-2P4XKWV2.js";
40
40
  import "./chunk-HO5R3ZRH.js";
41
41
  import "./chunk-6K64FJDD.js";
@@ -33,10 +33,10 @@ import {
33
33
  tryReservePort,
34
34
  tryReservePorts,
35
35
  worktreeRunPortsPath
36
- } from "./chunk-ZXWRNA4G.js";
37
- import "./chunk-ED4ZXQVO.js";
38
- import "./chunk-WQREAX35.js";
39
- import "./chunk-VXNZG4J6.js";
36
+ } from "./chunk-JM5P36PM.js";
37
+ import "./chunk-5XQ43YZU.js";
38
+ import "./chunk-5FMQU2RU.js";
39
+ import "./chunk-3IXGI2FP.js";
40
40
  import "./chunk-N2WW62LF.js";
41
41
  import "./chunk-DD67JWTN.js";
42
42
  import "./chunk-2UG25RMK.js";
@@ -47,7 +47,7 @@ import {
47
47
  } from "./chunk-WWUABK6B.js";
48
48
  import "./chunk-FJZWM2ON.js";
49
49
  import "./chunk-UN5Q7POQ.js";
50
- import "./chunk-TVN4TDFB.js";
50
+ import "./chunk-HTL4FBTP.js";
51
51
  import "./chunk-4RZRHTSZ.js";
52
52
  import "./chunk-KGZBYWZ3.js";
53
53
  import {
@@ -9,8 +9,8 @@ import {
9
9
  enrichWorkspacesWithGithub,
10
10
  ensureGlobalCoordinatorCwd,
11
11
  formatWorkspaceInventory
12
- } from "./chunk-WQREAX35.js";
13
- import "./chunk-VXNZG4J6.js";
12
+ } from "./chunk-5FMQU2RU.js";
13
+ import "./chunk-3IXGI2FP.js";
14
14
  import "./chunk-N2WW62LF.js";
15
15
  import "./chunk-DD67JWTN.js";
16
16
  import "./chunk-2UG25RMK.js";
@@ -19,7 +19,7 @@ import "./chunk-NSTQ6QKD.js";
19
19
  import "./chunk-WWUABK6B.js";
20
20
  import "./chunk-FJZWM2ON.js";
21
21
  import "./chunk-UN5Q7POQ.js";
22
- import "./chunk-TVN4TDFB.js";
22
+ import "./chunk-HTL4FBTP.js";
23
23
  import "./chunk-4RZRHTSZ.js";
24
24
  import "./chunk-KGZBYWZ3.js";
25
25
  import "./chunk-H5XL4KUS.js";
@@ -7,9 +7,9 @@ import {
7
7
  enrichWorkspacesWithGithub,
8
8
  ensureGlobalCoordinatorCwd,
9
9
  formatWorkspaceInventory
10
- } from "./chunk-BGEECLKH.js";
11
- import "./chunk-JWXJXEA3.js";
12
- import "./chunk-WZLV4WNS.js";
10
+ } from "./chunk-KMYCNSSI.js";
11
+ import "./chunk-BIMHIHX3.js";
12
+ import "./chunk-K5EACGG2.js";
13
13
  import "./chunk-2P4XKWV2.js";
14
14
  import "./chunk-6K64FJDD.js";
15
15
  import "./chunk-UWQ6UCIB.js";
@@ -18,9 +18,9 @@ import {
18
18
  remoteCoordinatorSourceRef,
19
19
  slackCoordinatorSourceRef,
20
20
  takenTeamSlugsForOrchestration
21
- } from "./chunk-BGEECLKH.js";
22
- import "./chunk-JWXJXEA3.js";
23
- import "./chunk-WZLV4WNS.js";
21
+ } from "./chunk-KMYCNSSI.js";
22
+ import "./chunk-BIMHIHX3.js";
23
+ import "./chunk-K5EACGG2.js";
24
24
  import "./chunk-2P4XKWV2.js";
25
25
  import "./chunk-6K64FJDD.js";
26
26
  import "./chunk-UWQ6UCIB.js";
@@ -20,8 +20,8 @@ import {
20
20
  remoteCoordinatorSourceRef,
21
21
  slackCoordinatorSourceRef,
22
22
  takenTeamSlugsForOrchestration
23
- } from "./chunk-WQREAX35.js";
24
- import "./chunk-VXNZG4J6.js";
23
+ } from "./chunk-5FMQU2RU.js";
24
+ import "./chunk-3IXGI2FP.js";
25
25
  import "./chunk-N2WW62LF.js";
26
26
  import "./chunk-DD67JWTN.js";
27
27
  import "./chunk-2UG25RMK.js";
@@ -30,7 +30,7 @@ import "./chunk-NSTQ6QKD.js";
30
30
  import "./chunk-WWUABK6B.js";
31
31
  import "./chunk-FJZWM2ON.js";
32
32
  import "./chunk-UN5Q7POQ.js";
33
- import "./chunk-TVN4TDFB.js";
33
+ import "./chunk-HTL4FBTP.js";
34
34
  import "./chunk-4RZRHTSZ.js";
35
35
  import "./chunk-KGZBYWZ3.js";
36
36
  import {