@sideboard-ai/core 0.1.297 → 0.1.299

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-IVKPCK56.js} +5 -5
  2. package/dist/{agents-DZTPUKVF.js → agents-JCCJJMA7.js} +5 -5
  3. package/dist/{chunk-VXNZG4J6.js → chunk-3IXGI2FP.js} +1 -1
  4. package/dist/{chunk-ED4ZXQVO.js → chunk-5XQ43YZU.js} +2 -1
  5. package/dist/{chunk-2O3ICR77.js → chunk-EB3F5AWV.js} +6 -4
  6. package/dist/{chunk-6GTABVNG.js → chunk-EB7B4D2Z.js} +6 -4
  7. package/dist/{chunk-Q3DPZ4DE.js → chunk-F36QRDM4.js} +2 -1
  8. package/dist/{chunk-ZXWRNA4G.js → chunk-F3JYJ4UB.js} +5 -5
  9. package/dist/{chunk-JWXJXEA3.js → chunk-G52HLBQR.js} +22 -2
  10. package/dist/{chunk-WZLV4WNS.js → chunk-K5EACGG2.js} +11 -0
  11. package/dist/{chunk-67BWWLEB.js → chunk-MMIDAD6J.js} +5 -5
  12. package/dist/{chunk-W2A63ZOK.js → chunk-NF3WDI7F.js} +501 -124
  13. package/dist/{chunk-BGEECLKH.js → chunk-QB4UQA5L.js} +10 -6
  14. package/dist/{chunk-WQREAX35.js → chunk-UMALFEDS.js} +10 -6
  15. package/dist/{chunk-QT36F4TD.js → chunk-YAILSKW3.js} +379 -64
  16. package/dist/{conductor-HJFDYIZD.js → conductor-JLHXMMKR.js} +5 -5
  17. package/dist/{conductor-ZXDIA6OF.js → conductor-UQDDDW35.js} +5 -5
  18. package/dist/{coordinator-prompt-ILHSVPOG.js → coordinator-prompt-HKLVS26O.js} +3 -3
  19. package/dist/{coordinator-prompt-L3V2CMWX.js → coordinator-prompt-SSUYZSJO.js} +3 -3
  20. package/dist/{global-workspace-47G453ZU.js → global-workspace-I32EWKX3.js} +3 -3
  21. package/dist/{global-workspace-NMRUGGFF.js → global-workspace-MHE6FCUZ.js} +3 -3
  22. package/dist/index.cjs +1125 -557
  23. package/dist/index.d.cts +60 -35
  24. package/dist/index.d.ts +60 -35
  25. package/dist/index.js +345 -230
  26. package/dist/mcp/run-stdio.cjs +816 -341
  27. package/dist/mcp/run-stdio.js +324 -218
  28. package/dist/{orchestrator-ZQU62CES.js → orchestrator-ESLNXVOX.js} +7 -7
  29. package/dist/{orchestrator-MR7TCIPP.js → orchestrator-SX4SGZHF.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-WGZPRQJX.js → workspaces-ATMIKXLK.js} +3 -3
  33. package/dist/{workspaces-PGY4UWZ3.js → workspaces-O3L32CDO.js} +3 -3
  34. package/dist/{worktree-JZXDAKQF.js → worktree-6G5X4ABY.js} +2 -2
  35. package/dist/{worktree-3MF5J5XZ.js → worktree-RMYXBTJG.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-EB7B4D2Z.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-MMIDAD6J.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,12 +100,13 @@ import {
100
100
  stageAbsolutePathsAsAttachments,
101
101
  stageBuffersAsAttachments,
102
102
  syncWorkspacesFromThreads
103
- } from "./chunk-BGEECLKH.js";
103
+ } from "./chunk-QB4UQA5L.js";
104
104
  import {
105
105
  addPrStackLayer,
106
106
  allocateTeamSlug,
107
107
  canonicalizeRepoPath,
108
108
  ciChecksFailed,
109
+ classifyPrMergeIssue,
109
110
  commitAll,
110
111
  connectedPrSelectors,
111
112
  createExistingBranchWorktree,
@@ -132,6 +133,7 @@ import {
132
133
  markPrReady,
133
134
  mergeAgentGitAuthEnv,
134
135
  mergePr,
136
+ mergeStateSuggestsCheckFailure,
135
137
  pushBranch,
136
138
  removeWorktree,
137
139
  resolveAgentGitAuthEnv,
@@ -142,7 +144,7 @@ import {
142
144
  resolveRepoRoot,
143
145
  switchWorktreeBranch,
144
146
  withRepoGitLock
145
- } from "./chunk-JWXJXEA3.js";
147
+ } from "./chunk-G52HLBQR.js";
146
148
  import {
147
149
  agentNicknameFromWorktreePath,
148
150
  appendMessage,
@@ -166,7 +168,7 @@ import {
166
168
  worktreeNameFromPath,
167
169
  worktreeSlugForTicket,
168
170
  writeThread
169
- } from "./chunk-WZLV4WNS.js";
171
+ } from "./chunk-K5EACGG2.js";
170
172
  import {
171
173
  createAgentStreamCoalescer
172
174
  } from "./chunk-AXQ4ZWHK.js";
@@ -451,9 +453,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
451
453
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
452
454
  );
453
455
  }
454
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-47G453ZU.js");
456
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-I32EWKX3.js");
455
457
  if (isGlobalThread2(thread)) {
456
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-ILHSVPOG.js");
458
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-HKLVS26O.js");
457
459
  ensureGlobalCoordinatorCwd2(
458
460
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
459
461
  );
@@ -1607,6 +1609,23 @@ function denyPendingToolPermissions(threadId) {
1607
1609
  if (last) clearPrompt(threadId, last.id);
1608
1610
  }
1609
1611
 
1612
+ // src/threads/connected-orchestrator.ts
1613
+ function connectedOrchestrator(thread, find) {
1614
+ if (isOrchestratorThread(thread)) return null;
1615
+ const seen = /* @__PURE__ */ new Set();
1616
+ let current = thread;
1617
+ for (let hop = 0; hop < 6 && current; hop++) {
1618
+ const parentId = current.parentThreadId?.trim();
1619
+ if (!parentId || seen.has(parentId)) return null;
1620
+ seen.add(parentId);
1621
+ const parent = find(parentId);
1622
+ if (!parent) return null;
1623
+ if (isOrchestratorThread(parent)) return parent;
1624
+ current = parent;
1625
+ }
1626
+ return null;
1627
+ }
1628
+
1610
1629
  // src/orchestrator/notify-orchestrator.ts
1611
1630
  var MAX_NOTIFY_ORCHESTRATOR_MESSAGE_CHARS = 1500;
1612
1631
  var inputRequiredNotified = /* @__PURE__ */ new Set();
@@ -1659,22 +1678,25 @@ function resolveNotifyCallerThread(opts) {
1659
1678
  return running;
1660
1679
  }
1661
1680
  function skipReason(opts) {
1662
- if (!opts.child.parentThreadId) {
1681
+ const parentId = opts.child.parentThreadId?.trim();
1682
+ if (!parentId) {
1663
1683
  return "This chat has no orchestrator parent. notify_orchestrator is for worktree children of a Global chat.";
1664
1684
  }
1665
- if (!opts.parent) {
1666
- return "Parent orchestration chat was not found.";
1667
- }
1668
- if (opts.parent.status === "archived") {
1685
+ if (opts.parent?.status === "archived") {
1669
1686
  return "Parent orchestration chat is archived.";
1670
1687
  }
1688
+ if (!opts.parent) {
1689
+ const immediate = readThread(parentId);
1690
+ if (!immediate) return "Parent orchestration chat was not found.";
1691
+ return "Parent is not a Global orchestration chat.";
1692
+ }
1671
1693
  if (!isOrchestratorThread(opts.parent)) {
1672
1694
  return "Parent is not a Global orchestration chat.";
1673
1695
  }
1674
1696
  return "Cannot notify orchestrator.";
1675
1697
  }
1676
1698
  async function notifyOrchestrator(input) {
1677
- const parent = input.child.parentThreadId ? readThread(input.child.parentThreadId) : null;
1699
+ const parent = connectedOrchestrator(input.child, (id) => readThread(id));
1678
1700
  if (!shouldNotifyOrchestrator({ child: input.child, parent })) {
1679
1701
  return { ok: false, error: skipReason({ child: input.child, parent }) };
1680
1702
  }
@@ -1981,20 +2003,7 @@ function threadCardBlockFields(group) {
1981
2003
  return block ? { blockedReason: block.reason, blockedSource: block.source } : null;
1982
2004
  }
1983
2005
 
1984
- // src/board/home-board.ts
1985
- var GLOBAL_WORKSPACE_ID = "__global__";
1986
- function isHomeBoardThread(thread) {
1987
- if (thread.sourceType === "orchestration") return false;
1988
- if (thread.repoPath === GLOBAL_WORKSPACE_ID) return false;
1989
- return true;
1990
- }
1991
- var BOARD_COLUMN_DEFS = [
1992
- { id: "new", title: "New" },
1993
- { id: "draft", title: "Draft" },
1994
- { id: "review", title: "Review" },
1995
- { id: "done", title: "Merged" }
1996
- ];
1997
- var HOME_BOARD_CACHE_TTL_MS = 15 * 60 * 1e3;
2006
+ // src/board/pr-state.ts
1998
2007
  function isOpenPrState(prUrl, prState) {
1999
2008
  if (!prUrl?.trim()) return false;
2000
2009
  const state = (prState ?? "OPEN").trim().toUpperCase();
@@ -2004,58 +2013,12 @@ function isMergedPrState(prUrl, prState) {
2004
2013
  if (!prUrl?.trim()) return false;
2005
2014
  return (prState ?? "").trim().toUpperCase() === "MERGED";
2006
2015
  }
2007
- var DEFAULT_WORKTREE_SORT = "created";
2008
- function groupCreatedAt(group) {
2009
- let min = group[0]?.createdAt ?? "";
2010
- for (const t of group) {
2011
- if (t.createdAt && t.createdAt < min) min = t.createdAt;
2012
- }
2013
- return min;
2014
- }
2015
- function groupUpdatedAt(group) {
2016
- let max = group[0]?.updatedAt ?? "";
2017
- for (const t of group) {
2018
- if (t.updatedAt && t.updatedAt > max) max = t.updatedAt;
2019
- }
2020
- return max;
2021
- }
2022
- function sortThreadsInWorktree(list) {
2023
- return [...list].sort((a, b) => {
2024
- const created = a.createdAt.localeCompare(b.createdAt);
2025
- if (created !== 0) return created;
2026
- return a.id.localeCompare(b.id);
2027
- });
2028
- }
2029
- function compareWorktreeGroups(a, b, mode, labelOf) {
2030
- if (mode === "name") {
2031
- const named = (labelOf?.(a) ?? a[0]?.id ?? "").localeCompare(
2032
- labelOf?.(b) ?? b[0]?.id ?? "",
2033
- void 0,
2034
- { sensitivity: "base" }
2035
- );
2036
- if (named !== 0) return named;
2037
- } else if (mode === "activity") {
2038
- const activity = groupUpdatedAt(b).localeCompare(groupUpdatedAt(a));
2039
- if (activity !== 0) return activity;
2040
- } else {
2041
- const created = groupCreatedAt(b).localeCompare(groupCreatedAt(a));
2042
- if (created !== 0) return created;
2043
- }
2044
- return (a[0]?.id ?? "").localeCompare(b[0]?.id ?? "");
2045
- }
2046
- function defaultWorktreeGroupLabel(group) {
2047
- return worktreeDisplayLabelForGroup(group);
2048
- }
2049
- function groupHomeBoardWorktrees(threads, sort = DEFAULT_WORKTREE_SORT, labelOf = defaultWorktreeGroupLabel) {
2050
- const map = /* @__PURE__ */ new Map();
2051
- for (const t of threads) {
2052
- const key = normalizeWorktreePath(t.worktreePath);
2053
- const list = map.get(key) ?? [];
2054
- list.push(t);
2055
- map.set(key, list);
2056
- }
2057
- return [...map.values()].map((list) => sortThreadsInWorktree(list)).sort((a, b) => compareWorktreeGroups(a, b, sort, labelOf));
2016
+ function isApprovedOpenPr(thread) {
2017
+ if (!isOpenPrState(thread.prUrl, thread.prState) || thread.prIsDraft) return false;
2018
+ return (thread.prReviewDecision ?? "").trim().toUpperCase() === "APPROVED";
2058
2019
  }
2020
+
2021
+ // src/board/worktree-ownership.ts
2059
2022
  var DEFAULT_BOARD_OWNERSHIP = "all";
2060
2023
  function normalizeViewerLogin(login) {
2061
2024
  return (login ?? "").trim().toLowerCase();
@@ -2086,16 +2049,8 @@ function worktreeMatchesOwnership(group, filter, viewerLogin = "") {
2086
2049
  if (filter === "all") return true;
2087
2050
  return classifyWorktreeOwnership(group, viewerLogin) === filter;
2088
2051
  }
2089
- function classifyWorktreeColumn(group) {
2090
- if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) return "done";
2091
- if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && !t.prIsDraft)) {
2092
- return "review";
2093
- }
2094
- if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && t.prIsDraft)) {
2095
- return "draft";
2096
- }
2097
- return "new";
2098
- }
2052
+
2053
+ // src/board/worktree-list-badges.ts
2099
2054
  function labelsInclude(labels, name) {
2100
2055
  const want = name.trim().toLowerCase();
2101
2056
  if (!want) return false;
@@ -2134,34 +2089,169 @@ function groupPrLabels(group) {
2134
2089
  }
2135
2090
  return out;
2136
2091
  }
2092
+ function isClosedPrState(prUrl, prState) {
2093
+ if (!prUrl?.trim()) return false;
2094
+ return (prState ?? "").trim().toUpperCase() === "CLOSED";
2095
+ }
2096
+ function listBadge(id, title, conflict = false) {
2097
+ return {
2098
+ id,
2099
+ label: id,
2100
+ title: conflict ? `${title} \xB7 merge conflicts` : title,
2101
+ mod: `is-${id}`,
2102
+ ...conflict ? { conflict: true } : {}
2103
+ };
2104
+ }
2105
+ function hasMergeConflict(thread) {
2106
+ if (!isOpenPrState(thread.prUrl, thread.prState)) return false;
2107
+ return classifyPrMergeIssue({
2108
+ mergeable: thread.prMergeable ?? null,
2109
+ mergeStateStatus: thread.prMergeStateStatus ?? null,
2110
+ isInMergeQueue: thread.prIsInMergeQueue
2111
+ }) === "conflicts";
2112
+ }
2113
+ function groupPrError(group) {
2114
+ const open = group.filter(
2115
+ (thread) => isOpenPrState(thread.prUrl, thread.prState) && !thread.prIsInMergeQueue
2116
+ );
2117
+ if (open.some(
2118
+ (thread) => thread.prChecksFailed || mergeStateSuggestsCheckFailure({
2119
+ mergeStateStatus: thread.prMergeStateStatus ?? null,
2120
+ reviewDecision: thread.prReviewDecision ?? null
2121
+ })
2122
+ )) {
2123
+ return { label: "failing", title: "Checks failing" };
2124
+ }
2125
+ if (open.some(
2126
+ (thread) => !thread.prIsDraft && (thread.prReviewDecision ?? "").trim().toUpperCase() === "CHANGES_REQUESTED"
2127
+ )) {
2128
+ return { label: "changes", title: "Changes requested" };
2129
+ }
2130
+ return void 0;
2131
+ }
2132
+ function withPrError(badges, error, conflict) {
2133
+ if (!error) return badges;
2134
+ const [first] = badges;
2135
+ if (!first) {
2136
+ return [
2137
+ {
2138
+ id: "error",
2139
+ label: error.label,
2140
+ title: conflict ? `${error.title} \xB7 merge conflicts` : error.title,
2141
+ mod: "is-error",
2142
+ ...conflict ? { conflict: true } : {}
2143
+ }
2144
+ ];
2145
+ }
2146
+ return [{ ...first, error }];
2147
+ }
2137
2148
  function classifyWorktreeListBadges(group, viewerLogin = "", reviewLabel = "") {
2138
2149
  if (group.length === 0 || group.some((t) => t.cowboy)) return [];
2150
+ if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) {
2151
+ return [listBadge("merged", "Merged")];
2152
+ }
2153
+ const conflict = group.some(hasMergeConflict);
2154
+ const error = groupPrError(group);
2155
+ const finish2 = (badges) => withPrError(badges, error, conflict);
2156
+ if (group.some((t) => isApprovedOpenPr(t))) {
2157
+ return finish2([listBadge("approved", "Approved, not merged", conflict)]);
2158
+ }
2139
2159
  const open = group.filter((t) => isOpenPrState(t.prUrl, t.prState));
2140
- if (open.length === 0) return [];
2160
+ if (open.length === 0) {
2161
+ if (group.some((t) => isClosedPrState(t.prUrl, t.prState))) return [];
2162
+ return finish2([listBadge("new", "No pull request")]);
2163
+ }
2141
2164
  const ownership = classifyWorktreeOwnership(group, viewerLogin);
2142
2165
  if (ownership === "reviewing") {
2143
- return [
2144
- {
2145
- id: "review",
2146
- label: "review",
2147
- title: "Someone else's PR",
2148
- mod: "is-review"
2149
- }
2150
- ];
2166
+ return finish2([listBadge("review", "Someone else's PR", conflict)]);
2167
+ }
2168
+ if (!normalizeViewerLogin(viewerLogin)) return finish2([]);
2169
+ if (!open.some((t) => !t.prIsDraft)) {
2170
+ return finish2([listBadge("draft", "Draft pull request", conflict)]);
2151
2171
  }
2152
- if (!normalizeViewerLogin(viewerLogin)) return [];
2153
- const draft = open.some((t) => t.prIsDraft);
2154
2172
  const readyLabel = reviewLabel.trim();
2155
- const inReview = readyLabel ? labelsInclude(groupPrLabels(group), readyLabel) : !draft;
2156
- if (!inReview) return [];
2157
- return [
2158
- {
2159
- id: "pending",
2160
- label: "pending",
2161
- title: "Waiting for review",
2162
- mod: "is-pending"
2163
- }
2164
- ];
2173
+ const inReview = readyLabel ? labelsInclude(groupPrLabels(group), readyLabel) : true;
2174
+ if (!inReview) return finish2([]);
2175
+ return finish2([listBadge("pending", "Waiting for review", conflict)]);
2176
+ }
2177
+
2178
+ // src/board/home-board.ts
2179
+ var GLOBAL_WORKSPACE_ID = "__global__";
2180
+ function isHomeBoardThread(thread) {
2181
+ if (thread.sourceType === "orchestration") return false;
2182
+ if (thread.repoPath === GLOBAL_WORKSPACE_ID) return false;
2183
+ return true;
2184
+ }
2185
+ var BOARD_COLUMN_DEFS = [
2186
+ { id: "new", title: "New" },
2187
+ { id: "draft", title: "Draft" },
2188
+ { id: "review", title: "Review" },
2189
+ { id: "approved", title: "Approved" },
2190
+ { id: "done", title: "Merged" }
2191
+ ];
2192
+ var HOME_BOARD_CACHE_TTL_MS = 15 * 60 * 1e3;
2193
+ var DEFAULT_WORKTREE_SORT = "created";
2194
+ function groupCreatedAt(group) {
2195
+ let min = group[0]?.createdAt ?? "";
2196
+ for (const t of group) {
2197
+ if (t.createdAt && t.createdAt < min) min = t.createdAt;
2198
+ }
2199
+ return min;
2200
+ }
2201
+ function groupUpdatedAt(group) {
2202
+ let max = group[0]?.updatedAt ?? "";
2203
+ for (const t of group) {
2204
+ if (t.updatedAt && t.updatedAt > max) max = t.updatedAt;
2205
+ }
2206
+ return max;
2207
+ }
2208
+ function sortThreadsInWorktree(list) {
2209
+ return [...list].sort((a, b) => {
2210
+ const created = a.createdAt.localeCompare(b.createdAt);
2211
+ if (created !== 0) return created;
2212
+ return a.id.localeCompare(b.id);
2213
+ });
2214
+ }
2215
+ function compareWorktreeGroups(a, b, mode, labelOf) {
2216
+ if (mode === "name") {
2217
+ const named = (labelOf?.(a) ?? a[0]?.id ?? "").localeCompare(
2218
+ labelOf?.(b) ?? b[0]?.id ?? "",
2219
+ void 0,
2220
+ { sensitivity: "base" }
2221
+ );
2222
+ if (named !== 0) return named;
2223
+ } else if (mode === "activity") {
2224
+ const activity = groupUpdatedAt(b).localeCompare(groupUpdatedAt(a));
2225
+ if (activity !== 0) return activity;
2226
+ } else {
2227
+ const created = groupCreatedAt(b).localeCompare(groupCreatedAt(a));
2228
+ if (created !== 0) return created;
2229
+ }
2230
+ return (a[0]?.id ?? "").localeCompare(b[0]?.id ?? "");
2231
+ }
2232
+ function defaultWorktreeGroupLabel(group) {
2233
+ return worktreeDisplayLabelForGroup(group);
2234
+ }
2235
+ function groupHomeBoardWorktrees(threads, sort = DEFAULT_WORKTREE_SORT, labelOf = defaultWorktreeGroupLabel) {
2236
+ const map = /* @__PURE__ */ new Map();
2237
+ for (const t of threads) {
2238
+ const key = normalizeWorktreePath(t.worktreePath);
2239
+ const list = map.get(key) ?? [];
2240
+ list.push(t);
2241
+ map.set(key, list);
2242
+ }
2243
+ return [...map.values()].map((list) => sortThreadsInWorktree(list)).sort((a, b) => compareWorktreeGroups(a, b, sort, labelOf));
2244
+ }
2245
+ function classifyWorktreeColumn(group) {
2246
+ if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) return "done";
2247
+ if (group.some((t) => isApprovedOpenPr(t))) return "approved";
2248
+ if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && !t.prIsDraft)) {
2249
+ return "review";
2250
+ }
2251
+ if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && t.prIsDraft)) {
2252
+ return "draft";
2253
+ }
2254
+ return "new";
2165
2255
  }
2166
2256
  function normalizeIssueKey(value) {
2167
2257
  return value.trim().toLowerCase().replace(/^#/, "");
@@ -2401,9 +2491,9 @@ var BOARD_PAGE_SIZE = 40;
2401
2491
  function tokenizeQuery(query) {
2402
2492
  return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
2403
2493
  }
2404
- function haystackMatches(haystack, tokens) {
2494
+ function haystackMatches(haystack2, tokens) {
2405
2495
  if (tokens.length === 0) return true;
2406
- const h = haystack.toLowerCase();
2496
+ const h = haystack2.toLowerCase();
2407
2497
  return tokens.every((token) => h.includes(token));
2408
2498
  }
2409
2499
  function prAuthorLogin(pr) {
@@ -2471,6 +2561,7 @@ function emptyColumns() {
2471
2561
  new: [],
2472
2562
  draft: [],
2473
2563
  review: [],
2564
+ approved: [],
2474
2565
  done: []
2475
2566
  };
2476
2567
  }
@@ -2482,6 +2573,7 @@ function emptyHidden() {
2482
2573
  new: 0,
2483
2574
  draft: 0,
2484
2575
  review: 0,
2576
+ approved: 0,
2485
2577
  done: 0
2486
2578
  };
2487
2579
  }
@@ -2550,6 +2642,7 @@ function assembleHomeBoard(input) {
2550
2642
  new: 0,
2551
2643
  draft: 0,
2552
2644
  review: 0,
2645
+ approved: 0,
2553
2646
  done: 0,
2554
2647
  tickets: 0,
2555
2648
  prs: 0,
@@ -2562,6 +2655,7 @@ function assembleHomeBoard(input) {
2562
2655
  new: [],
2563
2656
  draft: [],
2564
2657
  review: [],
2658
+ approved: [],
2565
2659
  done: []
2566
2660
  };
2567
2661
  for (const group of groupHomeBoardWorktrees(live)) {
@@ -2596,7 +2690,7 @@ function assembleHomeBoard(input) {
2596
2690
  }
2597
2691
  return { columns, hidden, totals };
2598
2692
  }
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.";
2693
+ 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 Approved (approved, not merged) \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
2694
 
2601
2695
  // src/threads/workspace-tags.ts
2602
2696
  function workspaceTagTargetRef(opts) {
@@ -2872,7 +2966,7 @@ async function createThread(input, _onSetupLine) {
2872
2966
  return readThread(thread.id) ?? thread;
2873
2967
  }
2874
2968
  async function listLinearIssues(agent, repoPath) {
2875
- const { getAdapter: getAdapter2 } = await import("./agents-ICHYDSCD.js");
2969
+ const { getAdapter: getAdapter2 } = await import("./agents-IVKPCK56.js");
2876
2970
  await requireAgent(agent, { requireLinear: true });
2877
2971
  const adapter = getAdapter2(agent);
2878
2972
  if (!adapter.listLinearIssues) {
@@ -2904,6 +2998,271 @@ function shouldRemoveWorktreeOnTeardown(thread) {
2904
2998
  return !isCowboyThread(thread) && !isPrimaryCheckoutThread(thread);
2905
2999
  }
2906
3000
 
3001
+ // src/archive/fleet-archive.ts
3002
+ import { basename as basename2 } from "path";
3003
+ var DEFAULT_LIMIT = 40;
3004
+ var MAX_LIMIT = 250;
3005
+ function oneLine(value) {
3006
+ return value.replace(/\s+/g, " ").trim();
3007
+ }
3008
+ function stampOf(thread) {
3009
+ return thread.archivedAt?.trim() || thread.updatedAt || thread.createdAt || "";
3010
+ }
3011
+ function repoLabel(thread) {
3012
+ if (isOrchestratorThread(thread)) return "Orchestration";
3013
+ const path = thread.repoPath?.trim() ?? "";
3014
+ return path && basename2(path) || path || "project";
3015
+ }
3016
+ function toAgent(thread, flags) {
3017
+ const prUrl = thread.prUrl?.trim();
3018
+ return {
3019
+ id: thread.id,
3020
+ title: thread.title?.trim() || "Untitled",
3021
+ agent: thread.agent,
3022
+ repo: repoLabel(thread),
3023
+ branch: thread.branchName ?? "",
3024
+ sourceType: thread.sourceType,
3025
+ sourceRef: thread.sourceRef,
3026
+ archivedAt: stampOf(thread),
3027
+ ...prUrl ? { prUrl } : {},
3028
+ ...flags?.workspaceLive ? { workspaceLive: true } : {},
3029
+ ...flags?.workspaceArchived ? { workspaceArchived: true } : {}
3030
+ };
3031
+ }
3032
+ function checkoutKey(thread) {
3033
+ return thread.worktreePath?.trim() ? normalizeWorktreePath(thread.worktreePath) : "";
3034
+ }
3035
+ function liveCheckoutKeys(threads) {
3036
+ const keys = /* @__PURE__ */ new Set();
3037
+ for (const thread of threads) {
3038
+ if (thread.status === "archived" || isOrchestratorThread(thread)) continue;
3039
+ const key = checkoutKey(thread);
3040
+ if (key) keys.add(key);
3041
+ }
3042
+ return keys;
3043
+ }
3044
+ function workspaceFrom(agents) {
3045
+ const ordered = [...agents].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
3046
+ const primary = ordered[0];
3047
+ const rows = ordered.map((thread) => toAgent(thread));
3048
+ const archivedAt = rows.reduce(
3049
+ (latest, row) => row.archivedAt > latest ? row.archivedAt : latest,
3050
+ ""
3051
+ );
3052
+ const prUrl = ordered.map((thread) => thread.prUrl?.trim()).find(Boolean);
3053
+ return {
3054
+ id: primary.id,
3055
+ title: primary.title?.trim() || "Untitled",
3056
+ repo: repoLabel(primary),
3057
+ branch: primary.branchName ?? "",
3058
+ sourceType: primary.sourceType,
3059
+ sourceRef: primary.sourceRef,
3060
+ archivedAt,
3061
+ ...prUrl ? { prUrl } : {},
3062
+ ...ordered.some((thread) => thread.cowboy) ? { cowboy: true } : {},
3063
+ agents: rows
3064
+ };
3065
+ }
3066
+ function haystack(parts) {
3067
+ return parts.filter(Boolean).join(" ").toLowerCase();
3068
+ }
3069
+ function agentHay(agent) {
3070
+ return haystack([
3071
+ agent.id,
3072
+ agent.title,
3073
+ agent.agent,
3074
+ agent.repo,
3075
+ agent.branch,
3076
+ agent.sourceType,
3077
+ agent.sourceRef,
3078
+ agent.prUrl
3079
+ ]);
3080
+ }
3081
+ function workspaceMatches(workspace, query) {
3082
+ if (!query) return true;
3083
+ const own = haystack([
3084
+ workspace.id,
3085
+ workspace.title,
3086
+ workspace.repo,
3087
+ workspace.branch,
3088
+ workspace.sourceType,
3089
+ workspace.sourceRef,
3090
+ workspace.prUrl
3091
+ ]);
3092
+ if (own.includes(query)) return true;
3093
+ return workspace.agents.some((agent) => agentHay(agent).includes(query));
3094
+ }
3095
+ function clampLimit(limit) {
3096
+ if (limit == null || !Number.isFinite(limit)) return DEFAULT_LIMIT;
3097
+ return Math.min(MAX_LIMIT, Math.max(1, Math.floor(limit)));
3098
+ }
3099
+ function listFleetArchive(threads, opts) {
3100
+ const query = opts?.query?.trim().toLowerCase() ?? "";
3101
+ const kind = opts?.kind ?? "all";
3102
+ const limit = clampLimit(opts?.limit);
3103
+ const liveKeys = liveCheckoutKeys(threads);
3104
+ const archived = threads.filter((thread) => thread.status === "archived");
3105
+ const groups = /* @__PURE__ */ new Map();
3106
+ const loose = [];
3107
+ for (const thread of archived) {
3108
+ const key = checkoutKey(thread);
3109
+ if (!key || isOrchestratorThread(thread) || liveKeys.has(key)) {
3110
+ loose.push(thread);
3111
+ continue;
3112
+ }
3113
+ const group = groups.get(key) ?? [];
3114
+ group.push(thread);
3115
+ groups.set(key, group);
3116
+ }
3117
+ const rows = [];
3118
+ if (kind !== "agent") {
3119
+ for (const group of groups.values()) {
3120
+ const workspace = workspaceFrom(group);
3121
+ if (!workspaceMatches(workspace, query)) continue;
3122
+ rows.push({ kind: "workspace", stamp: workspace.archivedAt, workspace });
3123
+ }
3124
+ }
3125
+ if (kind !== "workspace") {
3126
+ const pool = kind === "agent" ? archived : loose;
3127
+ for (const thread of pool) {
3128
+ const key = checkoutKey(thread);
3129
+ const orchestration = isOrchestratorThread(thread);
3130
+ const agent = toAgent(thread, {
3131
+ workspaceLive: Boolean(key) && !orchestration && liveKeys.has(key),
3132
+ workspaceArchived: Boolean(key) && !orchestration && !liveKeys.has(key)
3133
+ });
3134
+ if (query && !agentHay(agent).includes(query)) continue;
3135
+ rows.push({ kind: "agent", stamp: agent.archivedAt, agent });
3136
+ }
3137
+ }
3138
+ rows.sort((a, b) => {
3139
+ if (a.stamp !== b.stamp) return a.stamp < b.stamp ? 1 : -1;
3140
+ const idA = a.kind === "workspace" ? a.workspace.id : a.agent.id;
3141
+ const idB = b.kind === "workspace" ? b.workspace.id : b.agent.id;
3142
+ return idA.localeCompare(idB);
3143
+ });
3144
+ const page = rows.slice(0, limit);
3145
+ return {
3146
+ rows: page,
3147
+ shown: page.length,
3148
+ hidden: Math.max(0, rows.length - page.length),
3149
+ total: rows.length,
3150
+ query
3151
+ };
3152
+ }
3153
+ function archivedAgentsOnCheckout(threads, worktreePath) {
3154
+ const key = worktreePath.trim() ? normalizeWorktreePath(worktreePath) : "";
3155
+ if (!key) return [];
3156
+ return threads.filter(
3157
+ (thread) => thread.status === "archived" && !isOrchestratorThread(thread) && Boolean(thread.worktreePath?.trim()) && normalizeWorktreePath(thread.worktreePath) === key
3158
+ ).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
3159
+ }
3160
+ function formatWorkspaceLine(workspace) {
3161
+ const bits = [
3162
+ workspace.id.slice(0, 8),
3163
+ "workspace",
3164
+ workspace.repo,
3165
+ workspace.branch ? `branch:${workspace.branch}` : "",
3166
+ workspace.sourceType && workspace.sourceRef ? `${workspace.sourceType}:${workspace.sourceRef}` : "",
3167
+ `agents:${workspace.agents.length}`,
3168
+ workspace.cowboy ? "cowboy" : "",
3169
+ workspace.prUrl ?? "",
3170
+ workspace.archivedAt ? `archived:${workspace.archivedAt}` : "",
3171
+ oneLine(workspace.title)
3172
+ ].filter(Boolean);
3173
+ return bits.join(" ");
3174
+ }
3175
+ function formatAgentLine(agent) {
3176
+ const bits = [
3177
+ agent.id.slice(0, 8),
3178
+ "agent",
3179
+ agent.repo,
3180
+ agent.agent,
3181
+ agent.branch ? `branch:${agent.branch}` : "",
3182
+ agent.sourceType && agent.sourceRef ? `${agent.sourceType}:${agent.sourceRef}` : "",
3183
+ agent.workspaceLive ? "workspace-live" : "",
3184
+ agent.workspaceArchived ? "workspace-archived" : "",
3185
+ agent.prUrl ?? "",
3186
+ agent.archivedAt ? `archived:${agent.archivedAt}` : "",
3187
+ oneLine(agent.title),
3188
+ `sideboard://chat/${agent.id}`
3189
+ ].filter(Boolean);
3190
+ return bits.join(" ");
3191
+ }
3192
+ function formatFleetArchive(view) {
3193
+ if (view.total === 0) {
3194
+ return view.query ? "(no archive matches)" : "(archive empty)";
3195
+ }
3196
+ const lines = [
3197
+ `${view.shown} shown, ${view.hidden} hidden. restore_workspace <id> brings that checkout and every archived agent back. restore_chat <id> brings one agent back.`
3198
+ ];
3199
+ for (const row of view.rows) {
3200
+ if (row.kind === "workspace") {
3201
+ lines.push(formatWorkspaceLine(row.workspace));
3202
+ for (const agent of row.workspace.agents) {
3203
+ lines.push(
3204
+ ` ${agent.id.slice(0, 8)} ${agent.agent} ${oneLine(agent.title)} sideboard://chat/${agent.id}`
3205
+ );
3206
+ }
3207
+ continue;
3208
+ }
3209
+ lines.push(formatAgentLine(row.agent));
3210
+ }
3211
+ return lines.join("\n");
3212
+ }
3213
+
3214
+ // src/orchestrator/workspace-archive.ts
3215
+ function requireHostThread(host, ref) {
3216
+ const thread = host.getThread(ref);
3217
+ if (!thread) throw new Error(`Thread not found: ${ref}`);
3218
+ return thread;
3219
+ }
3220
+ async function archiveWorkspaceAgents(host, threadRef) {
3221
+ const thread = requireHostThread(host, threadRef);
3222
+ if (isOrchestratorThread(thread)) {
3223
+ throw new Error("Orchestration chats are agents, not workspaces. Use archive_chat.");
3224
+ }
3225
+ if (!thread.worktreePath?.trim()) {
3226
+ throw new Error("Chat has no workspace checkout. Use archive_chat.");
3227
+ }
3228
+ const chats = threadsSharingWorktree(thread.worktreePath);
3229
+ if (chats.length === 0) {
3230
+ throw new Error(
3231
+ "That workspace is already archived. Use list_archive, then restore_workspace to bring it back."
3232
+ );
3233
+ }
3234
+ const archived = [];
3235
+ for (const chat of chats) {
3236
+ archived.push(await host.archive(chat.id));
3237
+ }
3238
+ return archived;
3239
+ }
3240
+ async function restoreWorkspaceAgents(host, threadRef) {
3241
+ const thread = requireHostThread(host, threadRef);
3242
+ if (isOrchestratorThread(thread)) {
3243
+ throw new Error("Orchestration chats are agents, not workspaces. Use restore_chat.");
3244
+ }
3245
+ if (!thread.worktreePath?.trim()) {
3246
+ throw new Error("Chat has no workspace checkout. Use restore_chat.");
3247
+ }
3248
+ const targets = archivedAgentsOnCheckout(
3249
+ listThreads({ includeArchived: true }),
3250
+ thread.worktreePath
3251
+ );
3252
+ const restored = [];
3253
+ for (const chat of targets) {
3254
+ const latest = readThread(chat.id);
3255
+ if (!latest || latest.status !== "archived") continue;
3256
+ restored.push(await host.restore(latest.id));
3257
+ }
3258
+ if (restored.length === 0) {
3259
+ throw new Error(
3260
+ "No archived agents on this workspace. list_archive shows what can be restored."
3261
+ );
3262
+ }
3263
+ return restored;
3264
+ }
3265
+
2907
3266
  // src/util/line-coalescer.ts
2908
3267
  function createLineCoalescer(onChunk, opts) {
2909
3268
  const delayMs = opts?.delayMs ?? 50;
@@ -3383,7 +3742,7 @@ async function adoptThread(input) {
3383
3742
  messages: input.messages ?? []
3384
3743
  });
3385
3744
  writeThread(thread);
3386
- const { addWorkspace: addWorkspace2 } = await import("./workspaces-WGZPRQJX.js");
3745
+ const { addWorkspace: addWorkspace2 } = await import("./workspaces-ATMIKXLK.js");
3387
3746
  await addWorkspace2(repoPath);
3388
3747
  const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-RXZPTCNH.js");
3389
3748
  await ensureWorktreeSideboardIgnored(input.worktreePath);
@@ -5435,6 +5794,16 @@ function formatWorktreeDirective(thread, opts) {
5435
5794
  lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
5436
5795
  return lines.join("\n");
5437
5796
  }
5797
+ function formatConnectedOrchestratorReminder(parent) {
5798
+ if (!parent) return null;
5799
+ const title = parent.title?.trim() || "Orchestration";
5800
+ const archived = parent.status === "archived" ? " This orchestrator is archived." : "";
5801
+ 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}`;
5802
+ }
5803
+ function connectedOrchestratorTurnReminder(thread, find) {
5804
+ if (thread.agent === "brightsy" || isOrchestratorThread(thread)) return null;
5805
+ return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
5806
+ }
5438
5807
  function formatWorktreeReminder() {
5439
5808
  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
5809
  }
@@ -6302,7 +6671,7 @@ function formatScheduledPrompt(name, prompt) {
6302
6671
  ${prompt}`;
6303
6672
  }
6304
6673
  async function defaultDeps() {
6305
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-ZQU62CES.js");
6674
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-ESLNXVOX.js");
6306
6675
  const orch = getOrchestrator2();
6307
6676
  return {
6308
6677
  findThread: (id) => findThreadByRef(id),
@@ -7374,6 +7743,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
7374
7743
  );
7375
7744
  const turnReminders = [
7376
7745
  worktreeReminder,
7746
+ connectedOrchestratorTurnReminder(thread, (id) => readThread(id)),
7377
7747
  optionalServicesReminder,
7378
7748
  issueToolsReminder,
7379
7749
  reviewWriteGateReminder,
@@ -8971,14 +9341,16 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
8971
9341
  const thread = this.requireThread(threadRef);
8972
9342
  return threadsSharingWorktree(thread.worktreePath);
8973
9343
  }
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
9344
  enqueueWorktreeTeardown(thread, fn) {
8979
9345
  const key = isGlobalThread(thread) ? `archive:global:${thread.id}` : `archive:wt:${normalizeWorktreePath(thread.worktreePath)}`;
8980
9346
  return enqueueByKey(key, fn);
8981
9347
  }
9348
+ archiveWorkspace(threadRef) {
9349
+ return archiveWorkspaceAgents(this, threadRef);
9350
+ }
9351
+ restoreWorkspace(threadRef) {
9352
+ return restoreWorkspaceAgents(this, threadRef);
9353
+ }
8982
9354
  async archive(threadRef) {
8983
9355
  const thread = this.requireThread(threadRef);
8984
9356
  return this.enqueueWorktreeTeardown(thread, () => this.archiveUnlocked(threadRef));
@@ -9174,7 +9546,7 @@ async function startOrchestration(opts) {
9174
9546
  sourceRef: "default",
9175
9547
  ...createOpts
9176
9548
  }).catch(async () => {
9177
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-3MF5J5XZ.js");
9549
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-RMYXBTJG.js");
9178
9550
  const repo = await resolveRepoRoot2(repoPath);
9179
9551
  const def = await resolveDefaultBranch2(repo);
9180
9552
  return orch.createThread({
@@ -9184,7 +9556,7 @@ async function startOrchestration(opts) {
9184
9556
  repoPath: repo
9185
9557
  });
9186
9558
  });
9187
- const { updateThread: upd } = await import("./thread-store-SADLLKRE.js");
9559
+ const { updateThread: upd } = await import("./thread-store-WXLXKDVN.js");
9188
9560
  const updated = upd(thread.id, {
9189
9561
  sourceType: "orchestration",
9190
9562
  sourceRef: goal
@@ -9204,14 +9576,14 @@ export {
9204
9576
  worktreeBoardStatus,
9205
9577
  visibleAgentBlock,
9206
9578
  worktreeAgentBlock,
9579
+ reviewLabelForRepo,
9580
+ classifyWorktreeListBadges,
9207
9581
  isHomeBoardThread,
9208
9582
  BOARD_COLUMN_DEFS,
9209
9583
  HOME_BOARD_CACHE_TTL_MS,
9210
9584
  DEFAULT_WORKTREE_SORT,
9211
9585
  groupHomeBoardWorktrees,
9212
9586
  classifyWorktreeColumn,
9213
- reviewLabelForRepo,
9214
- classifyWorktreeListBadges,
9215
9587
  dedupeBoardIssues,
9216
9588
  issueNeedsWorkspacePick,
9217
9589
  isAccountWideIssueSource,
@@ -9273,6 +9645,7 @@ export {
9273
9645
  shouldRunHistoryCleanup,
9274
9646
  applyThreadIntoMain,
9275
9647
  cloneRepoIntoSideboard,
9648
+ connectedOrchestrator,
9276
9649
  formatAskUserNotifyMessage,
9277
9650
  formatNotifyOrchestratorPrompt,
9278
9651
  shouldNotifyOrchestrator,
@@ -9296,6 +9669,8 @@ export {
9296
9669
  isCowboyThread,
9297
9670
  isPrimaryCheckoutThread,
9298
9671
  shouldRemoveWorktreeOnTeardown,
9672
+ listFleetArchive,
9673
+ formatFleetArchive,
9299
9674
  readTurnLiveParts,
9300
9675
  readTurnLive,
9301
9676
  shouldStampSetupLastError,
@@ -9351,6 +9726,8 @@ export {
9351
9726
  localhostPreviewUrl,
9352
9727
  formatDevAccessHint,
9353
9728
  formatWorktreeDirective,
9729
+ formatConnectedOrchestratorReminder,
9730
+ connectedOrchestratorTurnReminder,
9354
9731
  formatWorktreeReminder,
9355
9732
  mentionsPrGoal,
9356
9733
  issueTicketFromThread,