@sideboard-ai/core 0.1.319 → 0.1.321

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 (75) hide show
  1. package/dist/{abletime-L3ODNTBT.js → abletime-CRRLEYTE.js} +4 -4
  2. package/dist/{abletime-DVYO4IVS.js → abletime-ICW6Q2AB.js} +4 -4
  3. package/dist/{abletime-oauth-2VWQCXGT.js → abletime-oauth-P3KPPJE4.js} +3 -3
  4. package/dist/{abletime-oauth-6DTX7LB7.js → abletime-oauth-Q76XBSPG.js} +3 -3
  5. package/dist/{abletime-rest-PYQM234B.js → abletime-rest-DNFAYYLP.js} +3 -3
  6. package/dist/{abletime-rest-7NICZYOC.js → abletime-rest-DQ3PNKXP.js} +3 -3
  7. package/dist/agents/cursor-runner.js +2 -2
  8. package/dist/{agents-KABJUDPI.js → agents-PFVYC36J.js} +10 -10
  9. package/dist/{agents-2AR7I6B6.js → agents-ROFDNE7Z.js} +11 -11
  10. package/dist/{app-settings-CZVFMOI5.js → app-settings-KMPVI2B7.js} +1 -1
  11. package/dist/{app-settings-V6YPYY57.js → app-settings-P3H4SEIK.js} +1 -1
  12. package/dist/{chunk-QVN2WOKJ.js → chunk-2TUE6JKQ.js} +12 -0
  13. package/dist/{chunk-OO3R6CS2.js → chunk-45UB2J47.js} +537 -90
  14. package/dist/{chunk-DD67JWTN.js → chunk-4YXZOXMT.js} +1 -1
  15. package/dist/{chunk-5OM7UCTQ.js → chunk-56M6VEXI.js} +3 -3
  16. package/dist/{chunk-ZM43NTJJ.js → chunk-5OQONGHO.js} +5 -5
  17. package/dist/{chunk-V5BTGQ6M.js → chunk-6U6QRUHY.js} +1 -1
  18. package/dist/{chunk-QPLQXWND.js → chunk-72PUPPV2.js} +3 -3
  19. package/dist/{chunk-53OCOGND.js → chunk-7JV5QP5K.js} +3 -3
  20. package/dist/{chunk-HOLB6ZFZ.js → chunk-B4CDSSRN.js} +2 -0
  21. package/dist/{chunk-ST2UQBJT.js → chunk-BANN5HUX.js} +8 -8
  22. package/dist/{chunk-AESO2KJS.js → chunk-BPDVHB4U.js} +3 -3
  23. package/dist/{chunk-WLZHRNE6.js → chunk-BTIXTH4N.js} +3 -3
  24. package/dist/{chunk-AUJ4XB6H.js → chunk-DFUXW2IT.js} +2 -2
  25. package/dist/{chunk-I5TESHDN.js → chunk-EQ52JR3Q.js} +5 -5
  26. package/dist/{chunk-E52SQENB.js → chunk-FZKAAAEB.js} +3 -1
  27. package/dist/{chunk-YALFZKSC.js → chunk-H6GXYV5Q.js} +23 -20
  28. package/dist/{chunk-JD7CC6SW.js → chunk-HHPTGIKS.js} +2 -2
  29. package/dist/{chunk-GCHSJCCX.js → chunk-IFU4W4C4.js} +3 -1
  30. package/dist/{chunk-YEIHCSZS.js → chunk-IFWGG2M2.js} +9 -0
  31. package/dist/{chunk-IAPO7ZFG.js → chunk-JNEFEA2A.js} +8 -8
  32. package/dist/{chunk-U2N32EA6.js → chunk-LD2DXHBP.js} +543 -92
  33. package/dist/{chunk-7Q327QF2.js → chunk-QIC2JXHW.js} +5 -5
  34. package/dist/{chunk-2P4XKWV2.js → chunk-QKHEVSB5.js} +1 -1
  35. package/dist/{chunk-NRSC4N5X.js → chunk-RGUZPMTF.js} +8 -8
  36. package/dist/{chunk-AZ4GEEGL.js → chunk-RHJKZOPQ.js} +3 -3
  37. package/dist/{chunk-HH3VVTEC.js → chunk-S5CJUIPY.js} +5 -5
  38. package/dist/{chunk-A6C67DY5.js → chunk-SPMIZSKH.js} +16 -13
  39. package/dist/{chunk-FDXHNROD.js → chunk-TEFFR6PB.js} +2 -2
  40. package/dist/{chunk-TUJFCJJU.js → chunk-UWJUARFA.js} +546 -187
  41. package/dist/{chunk-MBYGWNLQ.js → chunk-UX6EDDGR.js} +1 -1
  42. package/dist/{chunk-LXBZQP2Q.js → chunk-V76MQ7MH.js} +5 -5
  43. package/dist/{chunk-GH7UMULC.js → chunk-XDQSHSL6.js} +8 -8
  44. package/dist/{chunk-2UG25RMK.js → chunk-YBTSZ2SW.js} +12 -0
  45. package/dist/{chunk-A46CIARU.js → chunk-YWBLQBSN.js} +549 -188
  46. package/dist/{chunk-Y3Y7SZBZ.js → chunk-ZHGMRBSC.js} +1 -1
  47. package/dist/{conductor-MG2RAQNT.js → conductor-CNT3VL3S.js} +8 -8
  48. package/dist/{conductor-NIUBJLTS.js → conductor-XLXJU24U.js} +8 -8
  49. package/dist/{connected-teams-IHK2WXUI.js → connected-teams-H4LZOJDC.js} +2 -2
  50. package/dist/{connected-teams-IFW3NQ6G.js → connected-teams-XYRZMQO4.js} +2 -2
  51. package/dist/{coordinator-prompt-X74F3JIC.js → coordinator-prompt-D5EE2YTV.js} +6 -6
  52. package/dist/{coordinator-prompt-3CT3D5UM.js → coordinator-prompt-TU24TQ4I.js} +6 -6
  53. package/dist/{global-workspace-BUWMRNW5.js → global-workspace-743TPQNF.js} +6 -6
  54. package/dist/{global-workspace-FTNJEML3.js → global-workspace-UPMXDQM7.js} +6 -6
  55. package/dist/index.cjs +2160 -867
  56. package/dist/index.d.cts +211 -74
  57. package/dist/index.d.ts +211 -74
  58. package/dist/index.js +496 -78
  59. package/dist/mcp/run-stdio.cjs +1377 -478
  60. package/dist/mcp/run-stdio.js +80 -32
  61. package/dist/{optional-cli-6GGESWGE.js → optional-cli-2YDQQCCD.js} +5 -5
  62. package/dist/{optional-cli-EMSZBYDE.js → optional-cli-USD6PROE.js} +4 -4
  63. package/dist/{orchestrator-NCA4LSCC.js → orchestrator-B4STIW4B.js} +14 -14
  64. package/dist/{orchestrator-H3DSZ5RM.js → orchestrator-VQ4HRYVB.js} +13 -13
  65. package/dist/{run-PCX5QWR4.js → run-7QMRYP3F.js} +3 -1
  66. package/dist/{run-TB7RBII2.js → run-UPNCCRCN.js} +3 -1
  67. package/dist/{thread-store-PLNIWFZ4.js → thread-store-3F7GR64A.js} +1 -1
  68. package/dist/{thread-store-7BBA63KV.js → thread-store-JRSL4HQY.js} +1 -1
  69. package/dist/{workspaces-MGKEAYNM.js → workspaces-47WQL5IG.js} +6 -6
  70. package/dist/{workspaces-2V5UYPYC.js → workspaces-75FD4QUR.js} +6 -6
  71. package/dist/{worktree-XJKLDYOL.js → worktree-G3E6WP66.js} +11 -9
  72. package/dist/{worktree-THAXW5U7.js → worktree-PDNPL5CQ.js} +11 -9
  73. package/dist/{worktree-exclude-RXZPTCNH.js → worktree-exclude-INRDQFWV.js} +2 -2
  74. package/dist/{worktree-exclude-5N2KTYIT.js → worktree-exclude-P5NJODWP.js} +2 -2
  75. package/package.json +1 -1
@@ -6,7 +6,7 @@ import {
6
6
  import {
7
7
  formatOptionalServicesDirectiveForTurn,
8
8
  formatOptionalServicesReminderForTurn
9
- } from "./chunk-MBYGWNLQ.js";
9
+ } from "./chunk-UX6EDDGR.js";
10
10
  import {
11
11
  extractPresentedPlan,
12
12
  isPresentPlanToolName,
@@ -27,7 +27,7 @@ import {
27
27
  parseSessionQuotaResetAt,
28
28
  planModeTurnInstruction,
29
29
  resolveQuotaFallbackAgent
30
- } from "./chunk-GH7UMULC.js";
30
+ } from "./chunk-XDQSHSL6.js";
31
31
  import {
32
32
  applyWorktreePkgCacheEnv,
33
33
  askBlockStillWaiting,
@@ -65,7 +65,7 @@ import {
65
65
  worktreeDevProcessKey,
66
66
  worktreeRunProcessKey,
67
67
  worktreeSetupProcessKey
68
- } from "./chunk-NRSC4N5X.js";
68
+ } from "./chunk-RGUZPMTF.js";
69
69
  import {
70
70
  applyAgentEvent,
71
71
  clipAgentEventForPaint,
@@ -92,7 +92,7 @@ import {
92
92
  summarizeTurnStderr,
93
93
  toolDescription,
94
94
  turnFailChatText
95
- } from "./chunk-I5TESHDN.js";
95
+ } from "./chunk-EQ52JR3Q.js";
96
96
  import {
97
97
  SLACK_REPLY_FORMATTING,
98
98
  addWorkspace,
@@ -117,20 +117,23 @@ import {
117
117
  stageAbsolutePathsAsAttachments,
118
118
  stageBuffersAsAttachments,
119
119
  syncWorkspacesFromThreads
120
- } from "./chunk-A6C67DY5.js";
120
+ } from "./chunk-SPMIZSKH.js";
121
121
  import {
122
122
  addPrStackLayer,
123
123
  allocateTeamSlug,
124
124
  canonicalizeRepoPath,
125
125
  ciChecksFailed,
126
+ clampGithubPrBody,
126
127
  commitAll,
127
128
  connectedPrSelectors,
128
129
  createExistingBranchWorktree,
129
- createOrUpdatePr,
130
+ createOrUpdateCursorPr,
130
131
  createThreadWorktree,
131
132
  currentBranch,
132
133
  detectGhStack,
133
134
  enqueueByKey,
135
+ ensureGhPreferOrigin,
136
+ entireUsesTrails,
134
137
  fastForwardMainCheckoutIfSafe,
135
138
  fetchOriginForWorktree,
136
139
  fetchPrHead,
@@ -142,8 +145,11 @@ import {
142
145
  getPrForHeadBranch,
143
146
  getPrMeta,
144
147
  getPrStack,
148
+ ghHeadRef,
149
+ ghRepoSelectArgs,
145
150
  initPrStack,
146
151
  isDirty,
152
+ isGhRateLimitError,
147
153
  isSideboardScratchPath,
148
154
  listWorktrees,
149
155
  markPrReady,
@@ -155,18 +161,20 @@ import {
155
161
  resolveDefaultBranch,
156
162
  resolveDiffBaseRef,
157
163
  resolveGithubRepoSlug,
164
+ resolveOriginRemote,
158
165
  resolvePrSelector,
159
166
  resolveRepoRoot,
160
167
  switchWorktreeBranch,
161
168
  withRepoGitLock
162
- } from "./chunk-A46CIARU.js";
169
+ } from "./chunk-YWBLQBSN.js";
163
170
  import {
164
171
  clearStaleIndexLocks,
165
172
  enrichPathWithNpmGlobalBin,
166
173
  ensureAgentPath,
174
+ gh,
167
175
  git,
168
176
  resolveGitDirsForLockRecovery
169
- } from "./chunk-2UG25RMK.js";
177
+ } from "./chunk-YBTSZ2SW.js";
170
178
  import {
171
179
  HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT,
172
180
  applyTurnUsage,
@@ -201,7 +209,7 @@ import {
201
209
  usageOnLimit,
202
210
  withTurnScopedCost,
203
211
  writeViewerContext
204
- } from "./chunk-GCHSJCCX.js";
212
+ } from "./chunk-IFU4W4C4.js";
205
213
  import {
206
214
  writePrivateFile
207
215
  } from "./chunk-NSTQ6QKD.js";
@@ -242,7 +250,10 @@ import {
242
250
  worktreeNameFromPath,
243
251
  worktreeSlugForTicket,
244
252
  writeThread
245
- } from "./chunk-HOLB6ZFZ.js";
253
+ } from "./chunk-B4CDSSRN.js";
254
+ import {
255
+ normalizeThinkingEffort
256
+ } from "./chunk-KGZBYWZ3.js";
246
257
  import {
247
258
  annotateDevAccessRuns,
248
259
  appDataDir,
@@ -507,9 +518,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
507
518
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
508
519
  );
509
520
  }
510
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-BUWMRNW5.js");
521
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-743TPQNF.js");
511
522
  if (isGlobalThread2(thread)) {
512
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-3CT3D5UM.js");
523
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-TU24TQ4I.js");
513
524
  ensureGlobalCoordinatorCwd2(
514
525
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
515
526
  );
@@ -725,7 +736,9 @@ function resolveSidebarGitPrompt(action, opts) {
725
736
  }
726
737
  var RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
727
738
  var MERGE_INTO_RE = /^Merge PR into (.+)\.$/;
728
- function gitActionExpansion(action, base) {
739
+ function gitActionExpansion(action, base, forge) {
740
+ if (forge === "cursor") return cursorGitActionExpansion(action, base);
741
+ if (forge === "entire") return entireGitActionExpansion(action, base);
729
742
  switch (action) {
730
743
  case "commit-push":
731
744
  return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`; this updates an existing PR when one is linked). Do not start a checks loop unless a goal was given.";
@@ -750,7 +763,57 @@ function gitActionExpansion(action, base) {
750
763
  return "This phrase is the explicit ask to merge this thread's open pull request on GitHub. If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.";
751
764
  }
752
765
  }
753
- function expandCanonicalGitRequest(prompt) {
766
+ function cursorGitActionExpansion(action, base) {
767
+ switch (action) {
768
+ case "commit-push":
769
+ return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`; this updates an existing PR when one is linked). Use `origin`, not `gh`. Do not start a checks loop unless a goal was given.";
770
+ case "create-draft":
771
+ return "Commit, push, then create a draft PR with `origin pr create --draft --push -R <origin-owner/name> --body-file <short.md>` (title/body from the change purpose). Take the URL from `--json url`. Update the existing PR with `origin pr edit` if one is linked. Do not use `gh`.";
772
+ case "create-web":
773
+ return "Commit, push, then `origin pr create --push -R <origin-owner/name>` and open the URL from `--json url`. Origin has no `--web` form. Add `--draft` when they asked for a draft. Do not use `gh`.";
774
+ case "resolve-conflicts":
775
+ if (base && !isMainishPrBase(base)) {
776
+ return `Fetch \`origin/${base}\` (this PR's base \u2014 not main/master), merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable. Do not merge origin/main.`;
777
+ }
778
+ if (base) {
779
+ return `Fetch the PR base (\`${base}\`), merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
780
+ }
781
+ return "Look up this PR's base with `origin pr view --json baseRefName` and merge that remote branch into this branch (do not assume main). Resolve conflicts carefully, then commit and push until the PR is mergeable. Do not use `gh`.";
782
+ case "ready-for-review":
783
+ return "This phrase is the explicit ask to mark this thread's draft pull request ready for review on Cursor (`origin pr ready -R <origin-owner/name>`). Update title/body if the purpose drifted. Do not merge. Do not use `gh`.";
784
+ case "merge":
785
+ if (base && !isMainishPrBase(base)) {
786
+ return `This phrase is the explicit ask to merge this thread's open pull request into \`${base}\` on Cursor with \`origin pr merge\`. This PR targets \`${base}\`, not main \u2014 do not use \`origin stack merge\` and do not retarget or merge into main/master. Do not force-push main/master or merge locally into the main checkout. Do not use \`gh\`.`;
787
+ }
788
+ return "This phrase is the explicit ask to merge this thread's open pull request on Cursor. If `origin stack view` shows a stack, use `origin stack merge`; otherwise `origin pr merge`. Do not force-push main/master or merge locally into the main checkout. Do not use `gh`.";
789
+ }
790
+ }
791
+ function entireGitActionExpansion(action, base) {
792
+ switch (action) {
793
+ case "commit-push":
794
+ return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`). Use `entire`, not `gh` or `origin`. Do not start a checks loop unless a goal was given.";
795
+ case "create-draft":
796
+ return 'Commit, push, then open a Trail with `entire trail create --title "<title>" --body "<short>"` (title/body from the change purpose). Take the URL from `--json`. If this branch already has a trail, `entire trail update` instead of creating another. Trails have no draft flag. Do not use `gh` or `origin`.';
797
+ case "create-web":
798
+ return 'Commit, push, then `entire trail create --title "<title>" --body "<short>"` and open the URL from `--json`. Entire has no `--web` form. Do not use `gh` or `origin`.';
799
+ case "resolve-conflicts":
800
+ if (base && !isMainishPrBase(base)) {
801
+ return `Fetch \`origin/${base}\` (this Trail's base \u2014 not main/master), merge it into this branch, resolve conflicts carefully, then commit and push. Do not merge origin/main.`;
802
+ }
803
+ if (base) {
804
+ return `Fetch the Trail base (\`${base}\`), merge it into this branch, resolve conflicts carefully, then commit and push.`;
805
+ }
806
+ return "Look up this Trail's base with `entire trail show --json` and merge that remote branch into this branch (do not assume main). Resolve conflicts carefully, then commit and push. Do not use `gh`.";
807
+ case "ready-for-review":
808
+ return "This phrase means the Trail should be ready for a person to review. Trails have no draft flag and start open. Update title or body with `entire trail update` if the purpose drifted. Do not approve the trail and do not merge. Do not use `gh`.";
809
+ case "merge":
810
+ if (base && !isMainishPrBase(base)) {
811
+ return `This phrase is the explicit ask to merge this thread's Trail change into \`${base}\` with \`entire trail merge\`. This change targets \`${base}\`, not main \u2014 do not retarget or merge into main/master. Do not force-push main/master or merge locally into the main checkout. Do not use \`gh\`.`;
812
+ }
813
+ return "This phrase is the explicit ask to merge this thread's Trail change with `entire trail merge`. Do not force-push main/master or merge locally into the main checkout. Do not use `gh`.";
814
+ }
815
+ }
816
+ function expandCanonicalGitRequest(prompt, opts) {
754
817
  const trimmed = prompt.trim();
755
818
  let action = null;
756
819
  let base = null;
@@ -775,11 +838,12 @@ function expandCanonicalGitRequest(prompt) {
775
838
  base = m[1]?.trim() || null;
776
839
  }
777
840
  }
778
- let expansion = action ? gitActionExpansion(action, base) : null;
841
+ const forge = opts?.forge ?? null;
842
+ let expansion = action ? gitActionExpansion(action, base, forge) : null;
779
843
  if (!expansion && trimmed === "Address review comments.") {
780
- expansion = "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
844
+ expansion = forge === "cursor" ? "Read the PR review feedback (`origin pr view --comments`, `origin pr thread list`), make the requested changes, commit, and push. Do not use `gh`." : forge === "entire" ? "Read open findings (`entire trail finding list`), make the requested changes, commit, and push. Do not use `gh` or `entire trail comment` (agent sessions cannot post trail comments)." : "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
781
845
  } else if (!expansion && FIX_CI_RE.test(trimmed)) {
782
- expansion = "Investigate that failing check (`gh pr checks`, `gh run view --log-failed`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given.";
846
+ expansion = forge === "cursor" ? "Investigate that failing check (`origin pr checks`, `origin pr watch`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given. Do not use `gh run`." : forge === "entire" ? "Investigate the blocking gate (`entire trail merge --dry-run`, `entire trail finding list`, `entire trail watch`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given. Do not use `gh run`." : "Investigate that failing check (`gh pr checks`, `gh run view --log-failed`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given.";
783
847
  }
784
848
  if (!expansion) return prompt;
785
849
  return `${trimmed}
@@ -1955,6 +2019,71 @@ function claimSteerRequest(threadId) {
1955
2019
  });
1956
2020
  }
1957
2021
 
2022
+ // src/orchestrator/ephemeral-automation.ts
2023
+ function ephemeralRunReadyToArchive(thread) {
2024
+ if (!thread.ephemeralAutomationId?.trim()) return false;
2025
+ if (thread.status !== "idle" && thread.status !== "error") return false;
2026
+ if (thread.queue.length > 0) return false;
2027
+ if (thread.agentBlock?.reason?.trim()) return false;
2028
+ if (thread.quotaResumeAt) return false;
2029
+ return true;
2030
+ }
2031
+ function markEphemeralAutomation(threadId, opts) {
2032
+ const id = opts.ephemeralAutomationId?.trim();
2033
+ const current = readThread(threadId);
2034
+ if (!current) throw new Error(`Thread not found: ${threadId}`);
2035
+ if (!id) return current;
2036
+ const title = opts.ephemeralTitle?.trim();
2037
+ return updateThread(threadId, {
2038
+ ephemeralAutomationId: id,
2039
+ ...title ? { title, userSetTitle: true } : {}
2040
+ });
2041
+ }
2042
+ async function archiveEphemeralAutomationIfReady(threadId, archive) {
2043
+ const keep = await withThreadLock(threadId, async () => {
2044
+ const thread = readThread(threadId);
2045
+ if (!thread || !ephemeralRunReadyToArchive(thread)) return null;
2046
+ const automationId = thread.ephemeralAutomationId?.trim();
2047
+ if (!automationId) return null;
2048
+ await archive(thread.id);
2049
+ return {
2050
+ automationId,
2051
+ keepId: archivedContinuationId(automationId, threadId) ?? threadId
2052
+ };
2053
+ });
2054
+ if (keep) forgetOlderEphemeralRuns(keep.automationId, keep.keepId);
2055
+ }
2056
+ function archivedContinuationId(automationId, sourceId) {
2057
+ for (const thread of listThreads({ includeArchived: true })) {
2058
+ if (thread.id === sourceId || thread.status !== "archived") continue;
2059
+ if (thread.ephemeralAutomationId !== automationId) continue;
2060
+ if (thread.quotaContinuedFromId !== sourceId) continue;
2061
+ return thread.id;
2062
+ }
2063
+ return null;
2064
+ }
2065
+ function clearEphemeralAutomation(threadId) {
2066
+ const thread = readThread(threadId);
2067
+ if (!thread?.ephemeralAutomationId?.trim()) return;
2068
+ updateThread(threadId, { ephemeralAutomationId: void 0 });
2069
+ }
2070
+ function forgetOlderEphemeralRuns(automationId, keepId) {
2071
+ const id = automationId.trim();
2072
+ if (!id || !keepId) return [];
2073
+ const removed = [];
2074
+ for (const thread of listThreads({ includeArchived: true })) {
2075
+ if (thread.id === keepId) continue;
2076
+ if (thread.status !== "archived") continue;
2077
+ if (thread.ephemeralAutomationId !== id) continue;
2078
+ try {
2079
+ deleteThreadRecord(thread.id);
2080
+ removed.push(thread.id);
2081
+ } catch {
2082
+ }
2083
+ }
2084
+ return removed;
2085
+ }
2086
+
1958
2087
  // src/threads/agent-purpose-title.ts
1959
2088
  function agentPurposeStamp(input) {
1960
2089
  if (input.autoContinue) return null;
@@ -2632,7 +2761,7 @@ async function createThread(input, _onSetupLine) {
2632
2761
  });
2633
2762
  await requireAgent(resolved.agent);
2634
2763
  if (input.cowboy) {
2635
- const { cowboyModeEnabled } = await import("./app-settings-CZVFMOI5.js");
2764
+ const { cowboyModeEnabled } = await import("./app-settings-KMPVI2B7.js");
2636
2765
  if (!cowboyModeEnabled()) {
2637
2766
  throw new Error(
2638
2767
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -2691,7 +2820,7 @@ async function createThread(input, _onSetupLine) {
2691
2820
  let sourceIsFork = false;
2692
2821
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
2693
2822
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
2694
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-L3ODNTBT.js");
2823
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-CRRLEYTE.js");
2695
2824
  const task = await ensureAbleTimeTask({
2696
2825
  title: title?.trim() || "Untitled work",
2697
2826
  description: input.prompt?.trim() || void 0
@@ -3450,17 +3579,23 @@ async function isolateQuotaFailover(run) {
3450
3579
  }
3451
3580
  }
3452
3581
  function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
3582
+ const ephemeralAutomationId = from.ephemeralAutomationId?.trim();
3583
+ const ephemeralTitle = ephemeralAutomationId ? from.title.trim() : "";
3453
3584
  const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
3454
3585
  const tab = createChatTab({
3455
3586
  fromThreadId: from.id,
3456
3587
  agent: fallbackAgent,
3457
3588
  model: null,
3458
3589
  attachments: [handoff],
3590
+ ...ephemeralTitle ? { title: ephemeralTitle } : {},
3459
3591
  ...opts && "accountId" in opts ? { accountId: opts.accountId } : {}
3460
3592
  });
3461
3593
  const patch = {
3462
3594
  quotaContinuedFromId: from.id,
3463
- sourceRef: from.sourceRef
3595
+ sourceRef: from.sourceRef,
3596
+ // The original drain archives as idle. This sibling has to carry the one-off
3597
+ // so it archives when the continued turn finishes and History keeps it.
3598
+ ...ephemeralAutomationId ? { ephemeralAutomationId } : {}
3464
3599
  };
3465
3600
  if (isOrchestratorThread(from)) {
3466
3601
  patch.parentThreadId = from.id;
@@ -3552,7 +3687,7 @@ async function adoptThread(input) {
3552
3687
  throw new Error(`Worktree not found: ${input.worktreePath}`);
3553
3688
  }
3554
3689
  const repoPath = await resolveRepoRoot(input.worktreePath);
3555
- const { stdout: branch } = await import("./run-TB7RBII2.js").then(
3690
+ const { stdout: branch } = await import("./run-UPNCCRCN.js").then(
3556
3691
  ({ git: git2 }) => git2(["rev-parse", "--abbrev-ref", "HEAD"], input.worktreePath)
3557
3692
  );
3558
3693
  const thread = createEmptyThread({
@@ -3567,9 +3702,9 @@ async function adoptThread(input) {
3567
3702
  messages: input.messages ?? []
3568
3703
  });
3569
3704
  writeThread(thread);
3570
- const { addWorkspace: addWorkspace2 } = await import("./workspaces-2V5UYPYC.js");
3705
+ const { addWorkspace: addWorkspace2 } = await import("./workspaces-75FD4QUR.js");
3571
3706
  await addWorkspace2(repoPath);
3572
- const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-5N2KTYIT.js");
3707
+ const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-P5NJODWP.js");
3573
3708
  await ensureWorktreeSideboardIgnored(input.worktreePath);
3574
3709
  return thread;
3575
3710
  }
@@ -4048,9 +4183,177 @@ async function createPrStack(input, onSetupLine) {
4048
4183
  return { stack, threads, createdThreadIds };
4049
4184
  }
4050
4185
 
4186
+ // src/git/pr-write.ts
4187
+ import { randomBytes } from "crypto";
4188
+ import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
4189
+ import { tmpdir as tmpdir2 } from "os";
4190
+ import { join as join8 } from "path";
4191
+ async function lookupGithubGraphqlReset(cwd) {
4192
+ const result = await gh(["api", "rate_limit"], cwd, { reject: false });
4193
+ if (result.exitCode !== 0 || !result.stdout.trim()) return void 0;
4194
+ try {
4195
+ const data = JSON.parse(result.stdout);
4196
+ const reset = data.resources?.graphql?.reset;
4197
+ return typeof reset === "number" ? reset : void 0;
4198
+ } catch {
4199
+ return void 0;
4200
+ }
4201
+ }
4202
+ async function formatPrCreateFailure(raw, cwd, ctx) {
4203
+ if (!isGhRateLimitError(raw)) {
4204
+ return formatGhLandError(raw, {
4205
+ targetedRepo: ctx?.slug,
4206
+ headRef: ctx?.head
4207
+ });
4208
+ }
4209
+ const resetAt = await lookupGithubGraphqlReset(cwd);
4210
+ return formatGhLandError(raw, {
4211
+ resetAt,
4212
+ targetedRepo: ctx?.slug,
4213
+ headRef: ctx?.head
4214
+ });
4215
+ }
4216
+ async function createCursorPullRequest(worktreePath, slug, opts) {
4217
+ const bodyText = (opts.body ?? opts.title).trim() || opts.title;
4218
+ const bodyFile = join8(
4219
+ tmpdir2(),
4220
+ `sideboard-pr-body-${process.pid}-${randomBytes(6).toString("hex")}.md`
4221
+ );
4222
+ writeFileSync5(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
4223
+ `, "utf8");
4224
+ try {
4225
+ return await createOrUpdateCursorPr(worktreePath, slug, {
4226
+ title: opts.title,
4227
+ bodyFile,
4228
+ base: opts.base,
4229
+ head: opts.head,
4230
+ draft: opts.draft
4231
+ });
4232
+ } finally {
4233
+ try {
4234
+ unlinkSync3(bodyFile);
4235
+ } catch {
4236
+ }
4237
+ }
4238
+ }
4239
+ function ghPrCreateAssigneeArgs(assignee) {
4240
+ const raw = assignee?.trim();
4241
+ if (raw && /^(none|unassigned)$/i.test(raw)) return [];
4242
+ return ["--assignee", raw || "@me"];
4243
+ }
4244
+ async function createOrUpdatePr(worktreePath, opts) {
4245
+ const origin = await resolveOriginRemote(worktreePath);
4246
+ if (origin?.forge === "entire") throw entireUsesTrails();
4247
+ const cursorSlug = origin?.forge === "cursor" ? origin.slug : null;
4248
+ if (cursorSlug) return createCursorPullRequest(worktreePath, cursorSlug, opts);
4249
+ await ensureGhPreferOrigin(worktreePath);
4250
+ const slug = await resolveGithubRepoSlug(worktreePath);
4251
+ if (!slug) {
4252
+ throw new Error(
4253
+ "Could not resolve the origin GitHub repo (owner/name) for this worktree. Check that `git remote get-url origin` points at github.com."
4254
+ );
4255
+ }
4256
+ const repoArgs = ghRepoSelectArgs(slug);
4257
+ const headRef = ghHeadRef(slug, opts.head);
4258
+ const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
4259
+ const bodyText = clampGithubPrBody(opts.body ?? opts.title);
4260
+ const bodyFile = join8(
4261
+ tmpdir2(),
4262
+ `sideboard-pr-body-${process.pid}-${randomBytes(6).toString("hex")}.md`
4263
+ );
4264
+ writeFileSync5(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
4265
+ `, "utf8");
4266
+ const bodyArgs = ["--body-file", bodyFile];
4267
+ try {
4268
+ return await createOrUpdatePrWithBodyFile(worktreePath, {
4269
+ ...opts,
4270
+ slug,
4271
+ repoArgs,
4272
+ headRef,
4273
+ branchOnly,
4274
+ bodyArgs
4275
+ });
4276
+ } finally {
4277
+ try {
4278
+ unlinkSync3(bodyFile);
4279
+ } catch {
4280
+ }
4281
+ }
4282
+ }
4283
+ async function createOrUpdatePrWithBodyFile(worktreePath, opts) {
4284
+ const { slug, repoArgs, headRef, branchOnly, bodyArgs } = opts;
4285
+ const existing = await gh(
4286
+ [...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
4287
+ worktreePath,
4288
+ { reject: false }
4289
+ );
4290
+ if (existing.exitCode === 0 && existing.stdout.trim() && !opts.web) {
4291
+ const url2 = existing.stdout.trim();
4292
+ await gh(
4293
+ [
4294
+ ...repoArgs,
4295
+ "pr",
4296
+ "edit",
4297
+ branchOnly,
4298
+ "--title",
4299
+ opts.title,
4300
+ ...bodyArgs
4301
+ ],
4302
+ worktreePath,
4303
+ { reject: false }
4304
+ );
4305
+ return url2;
4306
+ }
4307
+ if (opts.web) {
4308
+ const args2 = [
4309
+ ...repoArgs,
4310
+ "pr",
4311
+ "create",
4312
+ "--web",
4313
+ "--title",
4314
+ opts.title,
4315
+ ...bodyArgs,
4316
+ "--base",
4317
+ opts.base,
4318
+ "--head",
4319
+ headRef
4320
+ ];
4321
+ if (opts.draft) args2.push("--draft");
4322
+ args2.push(...ghPrCreateAssigneeArgs(opts.assignee));
4323
+ await gh(args2, worktreePath, { reject: false });
4324
+ const again = await gh(
4325
+ [...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
4326
+ worktreePath,
4327
+ { reject: false }
4328
+ );
4329
+ return again.stdout.trim() || "";
4330
+ }
4331
+ const args = [
4332
+ ...repoArgs,
4333
+ "pr",
4334
+ "create",
4335
+ "--title",
4336
+ opts.title,
4337
+ ...bodyArgs,
4338
+ "--base",
4339
+ opts.base,
4340
+ "--head",
4341
+ headRef
4342
+ ];
4343
+ if (opts.draft) args.push("--draft");
4344
+ args.push(...ghPrCreateAssigneeArgs(opts.assignee));
4345
+ const created = await gh(args, worktreePath, { reject: false });
4346
+ if (created.exitCode !== 0) {
4347
+ const raw = created.stderr.trim() || created.stdout.trim() || "gh pr create failed";
4348
+ throw new Error(await formatPrCreateFailure(raw, worktreePath, { slug, head: headRef }));
4349
+ }
4350
+ const url = created.stdout.trim().split("\n").find((l) => l.startsWith("http")) ?? created.stdout.trim();
4351
+ return url;
4352
+ }
4353
+
4051
4354
  // src/diff/diff.ts
4052
- import { existsSync as existsSync9, mkdirSync, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
4053
- import { dirname as dirname2, join as join8 } from "path";
4355
+ import { existsSync as existsSync9, mkdirSync, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
4356
+ import { dirname as dirname2, join as join9 } from "path";
4054
4357
  async function inspectGitWorktree(worktreePath) {
4055
4358
  if (!worktreePath || !existsSync9(worktreePath)) return "missing_worktree";
4056
4359
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
@@ -4196,7 +4499,7 @@ new file mode 100644
4196
4499
  };
4197
4500
  }
4198
4501
  async function untrackedPatch(worktreePath, path, maxHunk) {
4199
- const abs = join8(worktreePath, path);
4502
+ const abs = join9(worktreePath, path);
4200
4503
  try {
4201
4504
  const st = statSync2(abs);
4202
4505
  if (st.isFile() && st.size > maxHunk) {
@@ -4668,7 +4971,7 @@ async function getDiff(worktreePath, repoPath, opts) {
4668
4971
  }
4669
4972
  function statWorktreePath(worktreePath, relativePath) {
4670
4973
  assertSafeRelativePath(relativePath);
4671
- const abs = join8(worktreePath, relativePath);
4974
+ const abs = join9(worktreePath, relativePath);
4672
4975
  if (!existsSync9(abs)) return "missing";
4673
4976
  const st = statSync2(abs);
4674
4977
  if (st.isDirectory()) return "dir";
@@ -4710,7 +5013,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
4710
5013
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
4711
5014
  assertSafeRelativePath(relativePath);
4712
5015
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
4713
- const abs = join8(worktreePath, relativePath);
5016
+ const abs = join9(worktreePath, relativePath);
4714
5017
  const st = statSync2(abs);
4715
5018
  if (!st.isFile()) {
4716
5019
  throw new Error(`Not a file: ${relativePath}`);
@@ -4730,7 +5033,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
4730
5033
  function readWorktreeFile(worktreePath, relativePath, opts) {
4731
5034
  assertSafeRelativePath(relativePath);
4732
5035
  const maxBytes = opts?.maxBytes ?? 2e5;
4733
- const abs = join8(worktreePath, relativePath);
5036
+ const abs = join9(worktreePath, relativePath);
4734
5037
  const st = statSync2(abs);
4735
5038
  if (!st.isFile()) {
4736
5039
  throw new Error(`Not a file: ${relativePath}`);
@@ -4778,9 +5081,9 @@ function assertSafeRelativePath(relativePath) {
4778
5081
  }
4779
5082
  function writeWorktreeFile(worktreePath, relativePath, content) {
4780
5083
  assertSafeRelativePath(relativePath);
4781
- const abs = join8(worktreePath, relativePath);
5084
+ const abs = join9(worktreePath, relativePath);
4782
5085
  mkdirSync(dirname2(abs), { recursive: true });
4783
- writeFileSync5(abs, content, "utf8");
5086
+ writeFileSync6(abs, content, "utf8");
4784
5087
  return { path: relativePath };
4785
5088
  }
4786
5089
  async function getWorktreeDirtyStat(worktreePath) {
@@ -4972,7 +5275,7 @@ async function confirmLand(thread, opts) {
4972
5275
  if (preview.dirty) {
4973
5276
  committed = await commitAll(thread.worktreePath, meta.commitMessage);
4974
5277
  }
4975
- const { git: git2 } = await import("./run-TB7RBII2.js");
5278
+ const { git: git2 } = await import("./run-UPNCCRCN.js");
4976
5279
  const { stdout: headOut } = await git2(
4977
5280
  ["rev-parse", "--abbrev-ref", "HEAD"],
4978
5281
  thread.worktreePath,
@@ -5003,13 +5306,13 @@ async function confirmLand(thread, opts) {
5003
5306
 
5004
5307
  // src/diff/read-worktree-tail.ts
5005
5308
  import { closeSync, fstatSync, openSync, readSync } from "fs";
5006
- import { join as join9 } from "path";
5309
+ import { join as join10 } from "path";
5007
5310
  var WORKTREE_TAIL_BYTES = 2e5;
5008
5311
  function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TAIL_BYTES) {
5009
5312
  if (!relativePath || relativePath.includes("..") || relativePath.startsWith("/")) {
5010
5313
  throw new Error("Invalid path");
5011
5314
  }
5012
- const abs = join9(worktreePath, relativePath);
5315
+ const abs = join10(worktreePath, relativePath);
5013
5316
  const fd = openSync(abs, "r");
5014
5317
  try {
5015
5318
  const st = fstatSync(fd);
@@ -5043,7 +5346,7 @@ function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TA
5043
5346
  // src/skills/discover.ts
5044
5347
  import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
5045
5348
  import { homedir } from "os";
5046
- import { join as join10 } from "path";
5349
+ import { join as join11 } from "path";
5047
5350
 
5048
5351
  // src/skills/bundled/long-running.ts
5049
5352
  var LONG_RUNNING_SKILL_COMMAND = "long-running";
@@ -5212,7 +5515,7 @@ function scanSkillsDir(dir, source, out) {
5212
5515
  }
5213
5516
  for (const entry of entries) {
5214
5517
  if (entry.startsWith(".")) continue;
5215
- const skillMd = join10(dir, entry, "SKILL.md");
5518
+ const skillMd = join11(dir, entry, "SKILL.md");
5216
5519
  if (!existsSync10(skillMd)) continue;
5217
5520
  try {
5218
5521
  if (!statSync3(skillMd).isFile()) continue;
@@ -5234,12 +5537,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
5234
5537
  return;
5235
5538
  }
5236
5539
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
5237
- const skill = readSkill(join10(dir, "SKILL.md"), "cli");
5540
+ const skill = readSkill(join11(dir, "SKILL.md"), "cli");
5238
5541
  if (skill) out.push(skill);
5239
5542
  }
5240
5543
  for (const entry of entries) {
5241
5544
  if (entry === "node_modules" || entry === ".git") continue;
5242
- const full = join10(dir, entry);
5545
+ const full = join11(dir, entry);
5243
5546
  try {
5244
5547
  if (!statSync3(full).isDirectory()) continue;
5245
5548
  } catch {
@@ -5259,17 +5562,17 @@ function discoverSkills(worktreePath) {
5259
5562
  const home = homedir();
5260
5563
  const collected = [];
5261
5564
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
5262
- scanSkillsDir(join10(worktreePath, rel), "workspace", collected);
5565
+ scanSkillsDir(join11(worktreePath, rel), "workspace", collected);
5263
5566
  }
5264
5567
  for (const abs of [
5265
- join10(home, ".claude/skills"),
5266
- join10(home, ".cursor/skills"),
5267
- join10(home, ".sideboard/skills"),
5268
- join10(home, ".brightsy/skills")
5568
+ join11(home, ".claude/skills"),
5569
+ join11(home, ".cursor/skills"),
5570
+ join11(home, ".sideboard/skills"),
5571
+ join11(home, ".brightsy/skills")
5269
5572
  ]) {
5270
5573
  scanSkillsDir(abs, "user", collected);
5271
5574
  }
5272
- scanClaudePluginSkills(join10(home, ".claude/plugins"), collected);
5575
+ scanClaudePluginSkills(join11(home, ".claude/plugins"), collected);
5273
5576
  collected.push(...bundledSkills());
5274
5577
  const rank = {
5275
5578
  workspace: 0,
@@ -5497,7 +5800,7 @@ function promptForJoinedSteer(input) {
5497
5800
  rewriteTrailingUserPrompt(input.threadId, input.promptText, input.latestPrompt);
5498
5801
  const { agentPrompt: expandedLatest } = expandComposerPrompt(
5499
5802
  input.worktreePath,
5500
- expandCanonicalGitRequest(input.latestPrompt),
5803
+ expandCanonicalGitRequest(input.latestPrompt, { forge: input.gitForge }),
5501
5804
  { attachments: input.attachments }
5502
5805
  );
5503
5806
  return input.expandedPrompt && input.agentPrompt.endsWith(input.expandedPrompt) ? input.agentPrompt.slice(0, -input.expandedPrompt.length) + expandedLatest : `${input.agentPrompt}
@@ -5593,11 +5896,33 @@ async function enqueueThreadSend(host, threadRef, prompt, opts) {
5593
5896
 
5594
5897
  // src/agents/instructions.ts
5595
5898
  import { existsSync as existsSync12 } from "fs";
5596
- import { join as join12 } from "path";
5899
+ import { join as join13 } from "path";
5900
+
5901
+ // src/agents/forge-git-directives.ts
5902
+ function formatCursorGitDirective(slug) {
5903
+ const repo = slug?.trim() || "<origin-owner/name>";
5904
+ return [
5905
+ `Git host (Settings \u2192 Git \u2192 Cursor): this checkout is on Cursor (\`origin.cursor.com\`, \`${repo}\`).`,
5906
+ "- Use the `origin` CLI, not `gh`. Where commands overlap, flags follow `gh` (`origin <command> --help`).",
5907
+ "- `origin` already authenticates from `CURSOR_AUTH_TOKEN`, then `CURSOR_API_KEY`, then the login stored in Settings \u2192 Git \u2192 Cursor. Do not read those values, set them, or run `origin auth login` from this turn.",
5908
+ "- Push with `git push -u origin HEAD`. If git asks for credentials, tell the user to open Settings \u2192 Git \u2192 Cursor and choose Configure git (`origin auth setup-git`). Do not wait for a Keychain dialog.",
5909
+ "- Origin has no issue tracker. Tickets for this repo come from Linear or AbleTime via `list_issues`. Do not use `gh issue`."
5910
+ ].join("\n");
5911
+ }
5912
+ function formatEntireGitDirective(slug) {
5913
+ const repo = slug?.trim() || "<origin-owner/name>";
5914
+ return [
5915
+ `Git host (Settings \u2192 Git \u2192 Entire): this checkout is on Entire (\`${repo}\`).`,
5916
+ "- Use the `entire` CLI, not `gh` or `origin`. Trails replace pull requests and GitHub issues.",
5917
+ "- `entire` uses the login from Settings \u2192 Git \u2192 Entire. Do not read tokens, set `ENTIRE_TOKEN`, or run `entire login` from this turn.",
5918
+ "- Push with `git push -u origin HEAD`. If git asks for credentials, tell the user to open Settings \u2192 Git \u2192 Entire and log in. Do not wait for a Keychain dialog.",
5919
+ "- Tickets for this repo are Trails (`entire trail list` / `entire trail show`). Do not use `gh issue`."
5920
+ ].join("\n");
5921
+ }
5597
5922
 
5598
5923
  // src/skills/detached-job-path.ts
5599
5924
  import { existsSync as existsSync11 } from "fs";
5600
- import { dirname as dirname3, join as join11 } from "path";
5925
+ import { dirname as dirname3, join as join12 } from "path";
5601
5926
  import { fileURLToPath } from "url";
5602
5927
  var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
5603
5928
  function compiledModuleDir() {
@@ -5614,7 +5939,7 @@ function compiledModuleDir() {
5614
5939
  }
5615
5940
  function detachedJobScriptIn(dir) {
5616
5941
  for (const name of DETACHED_JOB_FILENAMES) {
5617
- const script = join11(dir, "scripts", name);
5942
+ const script = join12(dir, "scripts", name);
5618
5943
  if (existsSync11(script)) return script;
5619
5944
  }
5620
5945
  return null;
@@ -5724,17 +6049,35 @@ function formatWorktreeDirective(thread, opts) {
5724
6049
  lines.push(
5725
6050
  "- Always use this worktree's `origin` remote (`git remote get-url origin` from this cwd). Never push to or open PRs against `upstream` (template remotes)."
5726
6051
  );
5727
- lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
6052
+ const cursorRepo = opts?.originForge === "cursor";
6053
+ const entireRepo = opts?.originForge === "entire";
6054
+ if (cursorRepo) {
6055
+ lines.push(formatCursorGitDirective(opts?.originSlug));
6056
+ } else if (entireRepo) {
6057
+ lines.push(formatEntireGitDirective(opts?.originSlug));
6058
+ } else {
6059
+ lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
6060
+ }
5728
6061
  lines.push(
5729
6062
  "- PR title/body and commit messages state what the change does and why (inspect the diff/commits and the user request) \u2014 never the worktree nickname or placeholder branch. Concise imperative title (Conventional Commits when it fits: feat:/fix:/chore:/docs:); body = intent, key changes, test notes."
5730
6063
  );
5731
6064
  lines.push(
5732
- "- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
6065
+ cursorRepo ? "- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via Origin from this worktree (`origin pr merge` / `origin stack merge`)." : entireRepo ? "- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge only when this turn is a Merge PR request or the user explicitly asked \u2014 via Entire from this worktree (`entire trail merge`)." : "- Stay on this workspace branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
5733
6066
  );
5734
6067
  if (thread.prUrl) {
5735
6068
  lines.push(
5736
6069
  `- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
5737
6070
  );
6071
+ } else if (entireRepo) {
6072
+ lines.push(
6073
+ '- Prefer a Trail: `entire trail create --title "<title>" --body "<short>"`. Take the URL from `--json`. If this branch already has a trail, `entire trail update` instead of creating another. Trails have no draft state. Do not use `gh` or `origin`.'
6074
+ );
6075
+ } else if (cursorRepo) {
6076
+ const slug = opts?.originSlug?.trim() || "<origin-owner/name>";
6077
+ const resolve = opts?.originSlug?.trim() ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
6078
+ lines.push(
6079
+ `- Prefer a draft PR first: \`origin pr create --draft --push -R ${slug}\` (update via \`origin pr edit -R ${slug}\`). Take the URL from \`--json url\` \u2014 do not build it. Do not use \`gh\`.${resolve} Mark ready only when asked (\`origin pr ready\`). If the body is too long, retry with a short \`--body-file\`.`
6080
+ );
5738
6081
  } else {
5739
6082
  const slug = opts?.githubSlug ?? "<origin-owner/name>";
5740
6083
  const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
@@ -5749,7 +6092,7 @@ function formatWorktreeDirective(thread, opts) {
5749
6092
  lines.push(formatDevAccessHint(opts?.activeRuns));
5750
6093
  lines.push("");
5751
6094
  lines.push(
5752
- "Schedules: `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `chatId=self` continues this chat; omit chatId for a new Global chat. Fires only while Sideboard.app is running. A future job turns on Settings \u2192 Advanced \u2192 Caffeinate while schedules are enabled."
6095
+ "Automations (sidebar, after Board): `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `chatId=self` continues this chat; omit chatId for a new Global chat. Fires only while Sideboard.app is running. A future job turns on Settings \u2192 Advanced \u2192 Caffeinate while automations are enabled."
5753
6096
  );
5754
6097
  lines.push(
5755
6098
  "`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
@@ -5769,7 +6112,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
5769
6112
  return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
5770
6113
  }
5771
6114
  function formatWorktreeReminder() {
5772
- 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).";
6115
+ 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. Automations: create_schedule (at / every / cron; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
5773
6116
  }
5774
6117
  function formatClaudeSubagentReminder() {
5775
6118
  return 'Claude subagents: if Task/Agent workers will edit files, write a short plan in this chat and continue in the same turn. Do not ask the user whether to isolate, and do not set worktree.bgIsolation to none. One writer may edit this workspace. Every other writer is an Agent with isolation "worktree" and a disjoint file list (read-only explore agents may overlap). While those agents run, leave their files alone. Merge each returned branch into this workspace, then remove the temporary worktree. You stay in this cwd. If Claude says another write-capable agent is in this directory, or that writes to the shared checkout are blocked, re-spawn that agent with isolation "worktree" or make the edit yourself. That note is another worker in this chat, or a worker Claude still has marked running. Do not mention it to the user.';
@@ -5855,9 +6198,9 @@ function formatPrGateDirective() {
5855
6198
  }
5856
6199
  function formatProcessGuideDirective(opts) {
5857
6200
  const worktree = opts?.worktreePath?.trim();
5858
- const hasGraphSkill = !!worktree && existsSync12(join12(worktree, ".claude/skills/graph-engineering/SKILL.md"));
5859
- const hasReviewSkill = !!worktree && existsSync12(join12(worktree, ".claude/skills/review/SKILL.md"));
5860
- const hasInstallSkill = !!worktree && existsSync12(join12(worktree, ".claude/skills/worktree-install/SKILL.md"));
6201
+ const hasGraphSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/graph-engineering/SKILL.md"));
6202
+ const hasReviewSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/review/SKILL.md"));
6203
+ const hasInstallSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/worktree-install/SKILL.md"));
5861
6204
  return [
5862
6205
  "Process guides (recurring work only):",
5863
6206
  hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
@@ -6011,6 +6354,7 @@ function compactIssueRow(issue, opts) {
6011
6354
  function formatMcpIssueList(input) {
6012
6355
  const truncated = input.truncated || Boolean(input.commentsTruncated);
6013
6356
  const comments = input.comments ?? [];
6357
+ const pageHint = input.unavailableReason ? input.unavailableReason : truncated ? input.since ? "More issues or comments match. Pass a higher limit (max 250) or a tighter query." : "More issues match. Pass a higher limit (max 250) or a tighter query." : void 0;
6014
6358
  return {
6015
6359
  ...input.source ? { source: input.source } : {},
6016
6360
  ...input.viewer ? { viewer: input.viewer } : {},
@@ -6018,9 +6362,8 @@ function formatMcpIssueList(input) {
6018
6362
  returned: input.issues.length,
6019
6363
  truncated,
6020
6364
  ...input.since ? { since: input.since } : {},
6021
- ...truncated ? {
6022
- hint: input.since ? "More issues or comments match. Pass a higher limit (max 250) or a tighter query." : "More issues match. Pass a higher limit (max 250) or a tighter query."
6023
- } : {},
6365
+ ...input.unavailableReason ? { unavailableReason: input.unavailableReason } : {},
6366
+ ...pageHint ? { hint: pageHint } : {},
6024
6367
  issues: input.issues.map((issue) => compactIssueRow(issue, { since: input.since })),
6025
6368
  ...input.since || comments.length > 0 ? { comments } : {}
6026
6369
  };
@@ -6037,7 +6380,8 @@ function formatListedIssuesForMcp(result, page) {
6037
6380
  truncated: windowed.truncated,
6038
6381
  since: result.since,
6039
6382
  comments: commentWindow.items,
6040
- commentsTruncated: commentWindow.truncated
6383
+ commentsTruncated: commentWindow.truncated,
6384
+ unavailableReason: result.unavailableReason
6041
6385
  });
6042
6386
  }
6043
6387
  function mcpJson(payload, isError = false) {
@@ -6365,7 +6709,7 @@ async function syncThreadBranchFromGit(threadId) {
6365
6709
  // src/store/schedules.ts
6366
6710
  import { randomUUID as randomUUID4 } from "crypto";
6367
6711
  import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
6368
- import { join as join13 } from "path";
6712
+ import { join as join14 } from "path";
6369
6713
  import { Cron } from "croner";
6370
6714
  var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
6371
6715
  var UNIT_MS = {
@@ -6375,7 +6719,7 @@ var UNIT_MS = {
6375
6719
  d: 864e5
6376
6720
  };
6377
6721
  function schedulesPath() {
6378
- return join13(appDataDir(), "schedules.json");
6722
+ return join14(appDataDir(), "schedules.json");
6379
6723
  }
6380
6724
  function parseDurationMs(every) {
6381
6725
  const m = every.trim().match(DURATION_RE);
@@ -6387,7 +6731,7 @@ function parseDurationMs(every) {
6387
6731
  }
6388
6732
  function defaultScheduleName(prompt) {
6389
6733
  const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
6390
- if (!line) return "Untitled schedule";
6734
+ if (!line) return "Untitled automation";
6391
6735
  return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
6392
6736
  }
6393
6737
  function resolveScheduleThreadId(raw, env = process.env) {
@@ -6452,6 +6796,45 @@ function normalizeWhen(raw) {
6452
6796
  }
6453
6797
  throw new Error("Schedule `when` must be once, every, or cron");
6454
6798
  }
6799
+ var ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
6800
+ "transcript",
6801
+ "file",
6802
+ "issue",
6803
+ "workspace",
6804
+ "diff-comment",
6805
+ "code-ref"
6806
+ ]);
6807
+ function normalizeOptionalBool(raw) {
6808
+ if (raw === true || raw === false) return raw;
6809
+ return null;
6810
+ }
6811
+ function normalizeAutonomy(raw) {
6812
+ return raw === "default" || raw === "full" ? raw : null;
6813
+ }
6814
+ function normalizeAttachments(raw) {
6815
+ if (!Array.isArray(raw)) return [];
6816
+ const out = [];
6817
+ for (const item of raw) {
6818
+ if (!item || typeof item !== "object") continue;
6819
+ const row = item;
6820
+ if (typeof row.id !== "string" || !row.id.trim()) continue;
6821
+ if (typeof row.name !== "string" || !row.name) continue;
6822
+ if (typeof row.content !== "string") continue;
6823
+ if (!ATTACHMENT_KINDS.has(row.kind)) continue;
6824
+ const next = {
6825
+ id: row.id,
6826
+ name: row.name,
6827
+ kind: row.kind,
6828
+ content: row.content
6829
+ };
6830
+ if (typeof row.path === "string" && row.path) next.path = row.path;
6831
+ if (typeof row.previewDataUrl === "string" && row.previewDataUrl) {
6832
+ next.previewDataUrl = row.previewDataUrl;
6833
+ }
6834
+ out.push(next);
6835
+ }
6836
+ return out;
6837
+ }
6455
6838
  function normalizeTask(raw) {
6456
6839
  const when = normalizeWhen(raw.when);
6457
6840
  const agent = raw.agent && isOrchestratorCapableAgent(raw.agent) ? raw.agent : null;
@@ -6464,6 +6847,11 @@ function normalizeTask(raw) {
6464
6847
  threadId: raw.threadId?.trim() || null,
6465
6848
  agent,
6466
6849
  model: raw.model?.trim() || null,
6850
+ effort: normalizeThinkingEffort(raw.effort),
6851
+ fast: normalizeOptionalBool(raw.fast),
6852
+ planMode: normalizeOptionalBool(raw.planMode),
6853
+ autonomy: normalizeAutonomy(raw.autonomy),
6854
+ attachments: normalizeAttachments(raw.attachments),
6467
6855
  nextRunAt: raw.nextRunAt,
6468
6856
  lastRunAt: raw.lastRunAt ?? null,
6469
6857
  lastThreadId: raw.lastThreadId ?? null,
@@ -6510,6 +6898,11 @@ function buildTask(input, now) {
6510
6898
  threadId: input.threadId?.trim() || null,
6511
6899
  agent,
6512
6900
  model: input.model?.trim() || null,
6901
+ effort: input.effort != null ? normalizeThinkingEffort(input.effort) : null,
6902
+ fast: normalizeOptionalBool(input.fast),
6903
+ planMode: normalizeOptionalBool(input.planMode),
6904
+ autonomy: normalizeAutonomy(input.autonomy),
6905
+ attachments: normalizeAttachments(input.attachments),
6513
6906
  nextRunAt,
6514
6907
  lastRunAt: null,
6515
6908
  lastThreadId: null,
@@ -6551,7 +6944,7 @@ function createSchedule(input) {
6551
6944
  function updateSchedule(id, patch) {
6552
6945
  const rows = readAll();
6553
6946
  const idx = rows.findIndex((row) => row.id === id || id.length >= 8 && row.id.startsWith(id));
6554
- if (idx < 0) throw new Error(`Schedule not found: ${id}`);
6947
+ if (idx < 0) throw new Error(`Automation not found: ${id}`);
6555
6948
  const prev = rows[idx];
6556
6949
  const when = patch.when ? normalizeWhen(patch.when) : prev.when;
6557
6950
  const prompt = patch.prompt !== void 0 ? patch.prompt.trim() : prev.prompt;
@@ -6566,6 +6959,11 @@ function updateSchedule(id, patch) {
6566
6959
  threadId: patch.threadId !== void 0 ? patch.threadId?.trim() || null : prev.threadId,
6567
6960
  agent: patch.agent !== void 0 ? patch.agent ? coerceOrchestratorAgent(patch.agent) : null : prev.agent,
6568
6961
  model: patch.model !== void 0 ? patch.model?.trim() || null : prev.model,
6962
+ effort: patch.effort !== void 0 ? normalizeThinkingEffort(patch.effort) : prev.effort,
6963
+ fast: patch.fast !== void 0 ? normalizeOptionalBool(patch.fast) : prev.fast,
6964
+ planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
6965
+ autonomy: patch.autonomy !== void 0 ? normalizeAutonomy(patch.autonomy) : prev.autonomy,
6966
+ attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
6569
6967
  nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
6570
6968
  lastError: whenChanged ? null : prev.lastError,
6571
6969
  updatedAt: nowIso()
@@ -6580,13 +6978,13 @@ function deleteSchedule(id) {
6580
6978
  const next = rows.filter(
6581
6979
  (row) => row.id !== id && !(id.length >= 8 && row.id.startsWith(id))
6582
6980
  );
6583
- if (next.length === rows.length) throw new Error(`Schedule not found: ${id}`);
6981
+ if (next.length === rows.length) throw new Error(`Automation not found: ${id}`);
6584
6982
  writeAll(next);
6585
6983
  }
6586
6984
  function recordScheduleRun(id, result) {
6587
6985
  const rows = readAll();
6588
6986
  const idx = rows.findIndex((row) => row.id === id);
6589
- if (idx < 0) throw new Error(`Schedule not found: ${id}`);
6987
+ if (idx < 0) throw new Error(`Automation not found: ${id}`);
6590
6988
  const prev = rows[idx];
6591
6989
  const firedAt = result.firedAt ?? /* @__PURE__ */ new Date();
6592
6990
  const next = {
@@ -6613,21 +7011,56 @@ function formatScheduledPrompt(name, prompt) {
6613
7011
  ${prompt}`;
6614
7012
  }
6615
7013
  async function defaultDeps() {
6616
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-H3DSZ5RM.js");
7014
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-VQ4HRYVB.js");
6617
7015
  const orch = getOrchestrator2();
6618
7016
  return {
6619
7017
  findThread: (id) => findThreadByRef(id),
6620
- send: (id, prompt) => orch.send(id, prompt),
7018
+ send: async (id, prompt, opts) => {
7019
+ if (opts?.options && Object.keys(opts.options).length > 0) {
7020
+ try {
7021
+ orch.setThreadOptions(id, opts.options);
7022
+ } catch {
7023
+ const rest = scheduleOptionsAfterRefusedAgentSwitch(opts.options);
7024
+ if (Object.keys(rest).length > 0) {
7025
+ try {
7026
+ orch.setThreadOptions(id, rest);
7027
+ } catch {
7028
+ }
7029
+ }
7030
+ }
7031
+ }
7032
+ const thread = findThreadByRef(id);
7033
+ const attachments = thread ? persistPendingFileAttachments(thread.worktreePath, opts?.attachments ?? []) : opts?.attachments ?? [];
7034
+ return orch.send(id, prompt, { attachments });
7035
+ },
6621
7036
  startOrchestration: (opts) => startOrchestration2(opts)
6622
7037
  };
6623
7038
  }
7039
+ function scheduleOptionsAfterRefusedAgentSwitch(options) {
7040
+ const { agent: _agent, model: _model, ...rest } = options;
7041
+ return rest;
7042
+ }
7043
+ function scheduleSendOptions(schedule) {
7044
+ const patch = {};
7045
+ if (schedule.agent) {
7046
+ patch.agent = schedule.agent;
7047
+ patch.model = schedule.model;
7048
+ } else if (schedule.model) {
7049
+ patch.model = schedule.model;
7050
+ }
7051
+ if (schedule.effort) patch.effort = schedule.effort;
7052
+ if (schedule.fast != null) patch.fast = schedule.fast;
7053
+ if (schedule.planMode != null) patch.planMode = schedule.planMode;
7054
+ if (schedule.autonomy) patch.autonomy = schedule.autonomy;
7055
+ return Object.keys(patch).length > 0 ? patch : void 0;
7056
+ }
6624
7057
  function pickAgent(schedule) {
6625
7058
  if (schedule.agent) return schedule.agent;
6626
7059
  return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
6627
7060
  }
6628
7061
  async function fireSchedule(id) {
6629
7062
  const schedule = getSchedule(id);
6630
- if (!schedule) throw new Error(`Schedule not found: ${id}`);
7063
+ if (!schedule) throw new Error(`Automation not found: ${id}`);
6631
7064
  if (firing.has(schedule.id)) return schedule;
6632
7065
  firing.add(schedule.id);
6633
7066
  try {
@@ -6635,18 +7068,28 @@ async function fireSchedule(id) {
6635
7068
  const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
6636
7069
  const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
6637
7070
  if (target && target.status !== "archived") {
6638
- const sent = await deps.send(target.id, prompt);
7071
+ const sent = await deps.send(target.id, prompt, {
7072
+ attachments: schedule.attachments,
7073
+ options: scheduleSendOptions(schedule)
7074
+ });
6639
7075
  return recordScheduleRun(schedule.id, {
6640
7076
  lastThreadId: sent.id,
6641
7077
  lastError: null
6642
7078
  });
6643
7079
  }
7080
+ const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
6644
7081
  const created = await deps.startOrchestration({
6645
7082
  goal: prompt,
6646
7083
  agent: pickAgent(schedule),
6647
- model: schedule.model
7084
+ model: schedule.model,
7085
+ ...schedule.effort ? { effort: schedule.effort } : {},
7086
+ ...schedule.fast != null ? { fast: schedule.fast } : {},
7087
+ ...schedule.planMode != null ? { planMode: schedule.planMode } : {},
7088
+ ...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
7089
+ attachments: schedule.attachments,
7090
+ ...pinReplacement ? {} : { ephemeralAutomationId: schedule.id, ephemeralTitle: schedule.name }
6648
7091
  });
6649
- if (schedule.threadId && schedule.when.kind !== "once") {
7092
+ if (pinReplacement) {
6650
7093
  updateSchedule(schedule.id, { threadId: created.id });
6651
7094
  }
6652
7095
  return recordScheduleRun(schedule.id, {
@@ -6934,7 +7377,7 @@ var Orchestrator = class {
6934
7377
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
6935
7378
  });
6936
7379
  }
6937
- const { autoCleanupOrphansEnabled } = await import("./app-settings-CZVFMOI5.js");
7380
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-KMPVI2B7.js");
6938
7381
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
6939
7382
  await cleanupOrphanWorktrees({ repoPaths });
6940
7383
  }
@@ -7328,7 +7771,7 @@ var Orchestrator = class {
7328
7771
  }
7329
7772
  await setup;
7330
7773
  if (skipSetup) return;
7331
- const { autoRunAfterSetupEnabled } = await import("./app-settings-CZVFMOI5.js");
7774
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-KMPVI2B7.js");
7332
7775
  if (autoRunAfterSetupEnabled()) {
7333
7776
  try {
7334
7777
  await this.startDev(threadId);
@@ -7537,6 +7980,7 @@ var Orchestrator = class {
7537
7980
  } finally {
7538
7981
  this.draining.delete(threadId);
7539
7982
  }
7983
+ await archiveEphemeralAutomationIfReady(threadId, (id) => this.archive(id));
7540
7984
  }
7541
7985
  async runTurn(threadId, prompt) {
7542
7986
  const existing = readThread(threadId);
@@ -7620,7 +8064,8 @@ var Orchestrator = class {
7620
8064
  return;
7621
8065
  }
7622
8066
  thread = this.requireThread(threadId);
7623
- const gitPrompt = expandCanonicalGitRequest(promptText);
8067
+ const turnOrigin = thread.worktreePath?.trim() ? await resolveOriginRemote(thread.worktreePath).catch(() => null) : null;
8068
+ const gitPrompt = expandCanonicalGitRequest(promptText, { forge: turnOrigin?.forge });
7624
8069
  const { agentPrompt: expandedPrompt } = expandComposerPrompt(
7625
8070
  thread.worktreePath,
7626
8071
  gitPrompt,
@@ -7704,14 +8149,12 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
7704
8149
  }
7705
8150
  const isBrightsy = fresh.agent === "brightsy";
7706
8151
  const isOrchestration = isOrchestratorThread(fresh);
7707
- const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-CZVFMOI5.js");
8152
+ const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-KMPVI2B7.js");
7708
8153
  const gitAuthMode = getGithubGitAuthMode();
7709
8154
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
7710
- githubSlug: await withTimeout(
7711
- resolveGithubRepoSlug(fresh.worktreePath),
7712
- 8e3,
7713
- "resolveGithubRepoSlug"
7714
- ).catch(() => null),
8155
+ githubSlug: turnOrigin?.forge === "github" ? turnOrigin.slug : await withTimeout(resolveGithubRepoSlug(fresh.worktreePath), 8e3, "resolveGithubRepoSlug").catch(() => null),
8156
+ originForge: turnOrigin?.forge ?? null,
8157
+ originSlug: turnOrigin?.slug ?? null,
7715
8158
  gitAuthMode,
7716
8159
  activeRuns: annotateDevAccessRuns(
7717
8160
  mergeWorktreeActiveRuns(
@@ -7804,7 +8247,8 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
7804
8247
  agentPrompt,
7805
8248
  expandedPrompt,
7806
8249
  worktreePath: fresh.worktreePath,
7807
- attachments: autoContinue ? [] : sentAttachments ?? []
8250
+ attachments: autoContinue ? [] : sentAttachments ?? [],
8251
+ gitForge: turnOrigin?.forge
7808
8252
  });
7809
8253
  const handle = await spawnAgentTurn(
7810
8254
  fresh,
@@ -9032,7 +9476,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9032
9476
  if (Object.keys(patch).length === 0) continue;
9033
9477
  updateThread(t.id, patch);
9034
9478
  }
9035
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-CZVFMOI5.js");
9479
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-KMPVI2B7.js");
9036
9480
  const latest = this.requireThread(thread.id);
9037
9481
  if (!shouldAutoArchiveOnPrMerge({
9038
9482
  previousPrState: prevState || null,
@@ -9356,7 +9800,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9356
9800
  await runArchiveScript(thread.repoPath, thread.worktreePath);
9357
9801
  } catch {
9358
9802
  }
9359
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-CZVFMOI5.js");
9803
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-KMPVI2B7.js");
9360
9804
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
9361
9805
  await removeWorktree(thread.repoPath, thread.worktreePath, {
9362
9806
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -9370,6 +9814,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9370
9814
  if (thread.status !== "archived") {
9371
9815
  throw new Error("Thread is not archived");
9372
9816
  }
9817
+ clearEphemeralAutomation(thread.id);
9373
9818
  if (isGlobalThread(thread)) {
9374
9819
  const { globalAgentCwd } = await import("./paths-HAAJNTTE.js");
9375
9820
  updateThread(thread.id, { worktreePath: globalAgentCwd() });
@@ -9387,7 +9832,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9387
9832
  await withRepoGitLock(thread.repoPath, async () => {
9388
9833
  await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
9389
9834
  });
9390
- const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-5N2KTYIT.js");
9835
+ const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-P5NJODWP.js");
9391
9836
  await ensureWorktreeSideboardIgnored(dest);
9392
9837
  }
9393
9838
  const restorePatch = {};
@@ -9469,10 +9914,11 @@ async function startOrchestration(opts) {
9469
9914
  planMode: opts.planMode,
9470
9915
  attachments: opts.attachments
9471
9916
  });
9917
+ const ready2 = markEphemeralAutomation(thread2.id, opts);
9472
9918
  if (goal) {
9473
- return orch.send(thread2.id, goal);
9919
+ return orch.send(ready2.id, goal);
9474
9920
  }
9475
- return thread2;
9921
+ return ready2;
9476
9922
  }
9477
9923
  const { titleFromPrompt: titleFromPrompt2 } = await import("./title-ERD6D3C3.js");
9478
9924
  const title = titleFromPrompt2(goal) || "Orchestration";
@@ -9492,7 +9938,7 @@ async function startOrchestration(opts) {
9492
9938
  sourceRef: "default",
9493
9939
  ...createOpts
9494
9940
  }).catch(async () => {
9495
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-XJKLDYOL.js");
9941
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-G3E6WP66.js");
9496
9942
  const repo = await resolveRepoRoot2(repoPath);
9497
9943
  const def = await resolveDefaultBranch2(repo);
9498
9944
  return orch.createThread({
@@ -9502,15 +9948,16 @@ async function startOrchestration(opts) {
9502
9948
  repoPath: repo
9503
9949
  });
9504
9950
  });
9505
- const { updateThread: upd } = await import("./thread-store-PLNIWFZ4.js");
9951
+ const { updateThread: upd } = await import("./thread-store-3F7GR64A.js");
9506
9952
  const updated = upd(thread.id, {
9507
9953
  sourceType: "orchestration",
9508
9954
  sourceRef: goal
9509
9955
  });
9956
+ const ready = markEphemeralAutomation(updated.id, opts);
9510
9957
  if (goal) {
9511
- return orch.send(updated.id, goal);
9958
+ return orch.send(ready.id, goal);
9512
9959
  }
9513
- return updated;
9960
+ return ready;
9514
9961
  }
9515
9962
 
9516
9963
  export {