@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
@@ -14,7 +14,7 @@ import {
14
14
  parseSessionQuotaResetAt,
15
15
  planModeTurnInstruction,
16
16
  resolveQuotaFallbackAgent
17
- } from "./chunk-IAPO7ZFG.js";
17
+ } from "./chunk-JNEFEA2A.js";
18
18
  import {
19
19
  applyWorktreePkgCacheEnv,
20
20
  askBlockStillWaiting,
@@ -52,7 +52,7 @@ import {
52
52
  worktreeDevProcessKey,
53
53
  worktreeRunProcessKey,
54
54
  worktreeSetupProcessKey
55
- } from "./chunk-ST2UQBJT.js";
55
+ } from "./chunk-BANN5HUX.js";
56
56
  import {
57
57
  applyAgentEvent,
58
58
  clipAgentEventForPaint,
@@ -67,14 +67,14 @@ import {
67
67
  partsToAssistantText,
68
68
  stripBrightsyNdjsonNoise,
69
69
  toolDescription
70
- } from "./chunk-7Q327QF2.js";
70
+ } from "./chunk-QIC2JXHW.js";
71
71
  import {
72
72
  titleFromPrompt
73
73
  } from "./chunk-7H655NEW.js";
74
74
  import {
75
75
  formatOptionalServicesDirectiveForTurn,
76
76
  formatOptionalServicesReminderForTurn
77
- } from "./chunk-FDXHNROD.js";
77
+ } from "./chunk-TEFFR6PB.js";
78
78
  import {
79
79
  SLACK_REPLY_FORMATTING,
80
80
  addWorkspace,
@@ -99,21 +99,24 @@ import {
99
99
  stageAbsolutePathsAsAttachments,
100
100
  stageBuffersAsAttachments,
101
101
  syncWorkspacesFromThreads
102
- } from "./chunk-YALFZKSC.js";
102
+ } from "./chunk-H6GXYV5Q.js";
103
103
  import {
104
104
  addPrStackLayer,
105
105
  allocateTeamSlug,
106
106
  canonicalizeRepoPath,
107
107
  ciChecksFailed,
108
+ clampGithubPrBody,
108
109
  classifyPrMergeIssue,
109
110
  commitAll,
110
111
  connectedPrSelectors,
111
112
  createExistingBranchWorktree,
112
- createOrUpdatePr,
113
+ createOrUpdateCursorPr,
113
114
  createThreadWorktree,
114
115
  currentBranch,
115
116
  detectGhStack,
116
117
  enqueueByKey,
118
+ ensureGhPreferOrigin,
119
+ entireUsesTrails,
117
120
  fastForwardMainCheckoutIfSafe,
118
121
  fetchOriginForWorktree,
119
122
  fetchPrHead,
@@ -125,8 +128,11 @@ import {
125
128
  getPrForHeadBranch,
126
129
  getPrMeta,
127
130
  getPrStack,
131
+ ghHeadRef,
132
+ ghRepoSelectArgs,
128
133
  initPrStack,
129
134
  isDirty,
135
+ isGhRateLimitError,
130
136
  isSideboardScratchPath,
131
137
  listWorktrees,
132
138
  markPrReady,
@@ -139,11 +145,12 @@ import {
139
145
  resolveDefaultBranch,
140
146
  resolveDiffBaseRef,
141
147
  resolveGithubRepoSlug,
148
+ resolveOriginRemote,
142
149
  resolvePrSelector,
143
150
  resolveRepoRoot,
144
151
  switchWorktreeBranch,
145
152
  withRepoGitLock
146
- } from "./chunk-TUJFCJJU.js";
153
+ } from "./chunk-UWJUARFA.js";
147
154
  import {
148
155
  REVIEW_TAB_TITLE,
149
156
  agentNicknameFromWorktreePath,
@@ -171,7 +178,7 @@ import {
171
178
  worktreeNameFromPath,
172
179
  worktreeSlugForTicket,
173
180
  writeThread
174
- } from "./chunk-YEIHCSZS.js";
181
+ } from "./chunk-IFWGG2M2.js";
175
182
  import {
176
183
  mcpServerIdForPermission,
177
184
  mcpServerPermissionUpdate
@@ -182,7 +189,7 @@ import {
182
189
  import {
183
190
  applyAgentRunnerHeapEnv,
184
191
  packagedMcpDir
185
- } from "./chunk-Y3Y7SZBZ.js";
192
+ } from "./chunk-ZHGMRBSC.js";
186
193
  import {
187
194
  fallbackTurnFailDetail,
188
195
  formatAgentErrorContinuePrompt,
@@ -202,9 +209,10 @@ import {
202
209
  clearStaleIndexLocks,
203
210
  enrichPathWithNpmGlobalBin,
204
211
  ensureAgentPath,
212
+ gh,
205
213
  git,
206
214
  resolveGitDirsForLockRecovery
207
- } from "./chunk-QVN2WOKJ.js";
215
+ } from "./chunk-2TUE6JKQ.js";
208
216
  import {
209
217
  HISTORY_CLEANUP_INTERVAL_HOURS_DEFAULT,
210
218
  applyTurnUsage,
@@ -239,7 +247,10 @@ import {
239
247
  usageOnLimit,
240
248
  withTurnScopedCost,
241
249
  writeViewerContext
242
- } from "./chunk-E52SQENB.js";
250
+ } from "./chunk-FZKAAAEB.js";
251
+ import {
252
+ normalizeThinkingEffort
253
+ } from "./chunk-77WWLBCI.js";
243
254
  import {
244
255
  examplePrefixedBranch,
245
256
  sanitizeGitBranchPrefix
@@ -461,9 +472,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
461
472
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
462
473
  );
463
474
  }
464
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-FTNJEML3.js");
475
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-UPMXDQM7.js");
465
476
  if (isGlobalThread2(thread)) {
466
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-X74F3JIC.js");
477
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-D5EE2YTV.js");
467
478
  ensureGlobalCoordinatorCwd2(
468
479
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
469
480
  );
@@ -679,7 +690,9 @@ function resolveSidebarGitPrompt(action, opts) {
679
690
  }
680
691
  var RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
681
692
  var MERGE_INTO_RE = /^Merge PR into (.+)\.$/;
682
- function gitActionExpansion(action, base) {
693
+ function gitActionExpansion(action, base, forge) {
694
+ if (forge === "cursor") return cursorGitActionExpansion(action, base);
695
+ if (forge === "entire") return entireGitActionExpansion(action, base);
683
696
  switch (action) {
684
697
  case "commit-push":
685
698
  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.";
@@ -704,7 +717,57 @@ function gitActionExpansion(action, base) {
704
717
  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.";
705
718
  }
706
719
  }
707
- function expandCanonicalGitRequest(prompt) {
720
+ function cursorGitActionExpansion(action, base) {
721
+ switch (action) {
722
+ case "commit-push":
723
+ 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.";
724
+ case "create-draft":
725
+ 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`.";
726
+ case "create-web":
727
+ 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`.";
728
+ case "resolve-conflicts":
729
+ if (base && !isMainishPrBase(base)) {
730
+ 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.`;
731
+ }
732
+ if (base) {
733
+ return `Fetch the PR base (\`${base}\`), merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
734
+ }
735
+ 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`.";
736
+ case "ready-for-review":
737
+ 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`.";
738
+ case "merge":
739
+ if (base && !isMainishPrBase(base)) {
740
+ 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\`.`;
741
+ }
742
+ 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`.";
743
+ }
744
+ }
745
+ function entireGitActionExpansion(action, base) {
746
+ switch (action) {
747
+ case "commit-push":
748
+ 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.";
749
+ case "create-draft":
750
+ 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`.';
751
+ case "create-web":
752
+ 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`.';
753
+ case "resolve-conflicts":
754
+ if (base && !isMainishPrBase(base)) {
755
+ 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.`;
756
+ }
757
+ if (base) {
758
+ return `Fetch the Trail base (\`${base}\`), merge it into this branch, resolve conflicts carefully, then commit and push.`;
759
+ }
760
+ 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`.";
761
+ case "ready-for-review":
762
+ 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`.";
763
+ case "merge":
764
+ if (base && !isMainishPrBase(base)) {
765
+ 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\`.`;
766
+ }
767
+ 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`.";
768
+ }
769
+ }
770
+ function expandCanonicalGitRequest(prompt, opts) {
708
771
  const trimmed = prompt.trim();
709
772
  let action = null;
710
773
  let base = null;
@@ -729,11 +792,12 @@ function expandCanonicalGitRequest(prompt) {
729
792
  base = m[1]?.trim() || null;
730
793
  }
731
794
  }
732
- let expansion = action ? gitActionExpansion(action, base) : null;
795
+ const forge = opts?.forge ?? null;
796
+ let expansion = action ? gitActionExpansion(action, base, forge) : null;
733
797
  if (!expansion && trimmed === "Address review comments.") {
734
- expansion = "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
798
+ 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.";
735
799
  } else if (!expansion && FIX_CI_RE.test(trimmed)) {
736
- 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.";
800
+ 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.";
737
801
  }
738
802
  if (!expansion) return prompt;
739
803
  return `${trimmed}
@@ -2074,6 +2138,71 @@ function claimSteerRequest(threadId) {
2074
2138
  });
2075
2139
  }
2076
2140
 
2141
+ // src/orchestrator/ephemeral-automation.ts
2142
+ function ephemeralRunReadyToArchive(thread) {
2143
+ if (!thread.ephemeralAutomationId?.trim()) return false;
2144
+ if (thread.status !== "idle" && thread.status !== "error") return false;
2145
+ if (thread.queue.length > 0) return false;
2146
+ if (thread.agentBlock?.reason?.trim()) return false;
2147
+ if (thread.quotaResumeAt) return false;
2148
+ return true;
2149
+ }
2150
+ function markEphemeralAutomation(threadId, opts) {
2151
+ const id = opts.ephemeralAutomationId?.trim();
2152
+ const current = readThread(threadId);
2153
+ if (!current) throw new Error(`Thread not found: ${threadId}`);
2154
+ if (!id) return current;
2155
+ const title = opts.ephemeralTitle?.trim();
2156
+ return updateThread(threadId, {
2157
+ ephemeralAutomationId: id,
2158
+ ...title ? { title, userSetTitle: true } : {}
2159
+ });
2160
+ }
2161
+ async function archiveEphemeralAutomationIfReady(threadId, archive) {
2162
+ const keep = await withThreadLock(threadId, async () => {
2163
+ const thread = readThread(threadId);
2164
+ if (!thread || !ephemeralRunReadyToArchive(thread)) return null;
2165
+ const automationId = thread.ephemeralAutomationId?.trim();
2166
+ if (!automationId) return null;
2167
+ await archive(thread.id);
2168
+ return {
2169
+ automationId,
2170
+ keepId: archivedContinuationId(automationId, threadId) ?? threadId
2171
+ };
2172
+ });
2173
+ if (keep) forgetOlderEphemeralRuns(keep.automationId, keep.keepId);
2174
+ }
2175
+ function archivedContinuationId(automationId, sourceId) {
2176
+ for (const thread of listThreads({ includeArchived: true })) {
2177
+ if (thread.id === sourceId || thread.status !== "archived") continue;
2178
+ if (thread.ephemeralAutomationId !== automationId) continue;
2179
+ if (thread.quotaContinuedFromId !== sourceId) continue;
2180
+ return thread.id;
2181
+ }
2182
+ return null;
2183
+ }
2184
+ function clearEphemeralAutomation(threadId) {
2185
+ const thread = readThread(threadId);
2186
+ if (!thread?.ephemeralAutomationId?.trim()) return;
2187
+ updateThread(threadId, { ephemeralAutomationId: void 0 });
2188
+ }
2189
+ function forgetOlderEphemeralRuns(automationId, keepId) {
2190
+ const id = automationId.trim();
2191
+ if (!id || !keepId) return [];
2192
+ const removed = [];
2193
+ for (const thread of listThreads({ includeArchived: true })) {
2194
+ if (thread.id === keepId) continue;
2195
+ if (thread.status !== "archived") continue;
2196
+ if (thread.ephemeralAutomationId !== id) continue;
2197
+ try {
2198
+ deleteThreadRecord(thread.id);
2199
+ removed.push(thread.id);
2200
+ } catch {
2201
+ }
2202
+ }
2203
+ return removed;
2204
+ }
2205
+
2077
2206
  // src/threads/agent-purpose-title.ts
2078
2207
  function agentPurposeStamp(input) {
2079
2208
  if (input.autoContinue) return null;
@@ -2930,7 +3059,7 @@ async function createThread(input, _onSetupLine) {
2930
3059
  });
2931
3060
  await requireAgent(resolved.agent);
2932
3061
  if (input.cowboy) {
2933
- const { cowboyModeEnabled } = await import("./app-settings-V6YPYY57.js");
3062
+ const { cowboyModeEnabled } = await import("./app-settings-P3H4SEIK.js");
2934
3063
  if (!cowboyModeEnabled()) {
2935
3064
  throw new Error(
2936
3065
  "Cowboy mode is off. Enable it in Settings \u2192 Advanced."
@@ -2989,7 +3118,7 @@ async function createThread(input, _onSetupLine) {
2989
3118
  let sourceIsFork = false;
2990
3119
  if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
2991
3120
  if (isAbleTimeConnected() && getIssueSource() === "abletime") {
2992
- const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-DVYO4IVS.js");
3121
+ const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-ICW6Q2AB.js");
2993
3122
  const task = await ensureAbleTimeTask({
2994
3123
  title: title?.trim() || "Untitled work",
2995
3124
  description: input.prompt?.trim() || void 0
@@ -3100,7 +3229,7 @@ async function createThread(input, _onSetupLine) {
3100
3229
  return readThread(thread.id) ?? thread;
3101
3230
  }
3102
3231
  async function listLinearIssues(agent, repoPath) {
3103
- const { getAdapter: getAdapter2 } = await import("./agents-2AR7I6B6.js");
3232
+ const { getAdapter: getAdapter2 } = await import("./agents-ROFDNE7Z.js");
3104
3233
  await requireAgent(agent, { requireLinear: true });
3105
3234
  const adapter = getAdapter2(agent);
3106
3235
  if (!adapter.listLinearIssues) {
@@ -3760,17 +3889,23 @@ async function isolateQuotaFailover(run) {
3760
3889
  }
3761
3890
  }
3762
3891
  function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
3892
+ const ephemeralAutomationId = from.ephemeralAutomationId?.trim();
3893
+ const ephemeralTitle = ephemeralAutomationId ? from.title.trim() : "";
3763
3894
  const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
3764
3895
  const tab = createChatTab({
3765
3896
  fromThreadId: from.id,
3766
3897
  agent: fallbackAgent,
3767
3898
  model: null,
3768
3899
  attachments: [handoff],
3900
+ ...ephemeralTitle ? { title: ephemeralTitle } : {},
3769
3901
  ...opts && "accountId" in opts ? { accountId: opts.accountId } : {}
3770
3902
  });
3771
3903
  const patch = {
3772
3904
  quotaContinuedFromId: from.id,
3773
- sourceRef: from.sourceRef
3905
+ sourceRef: from.sourceRef,
3906
+ // The original drain archives as idle. This sibling has to carry the one-off
3907
+ // so it archives when the continued turn finishes and History keeps it.
3908
+ ...ephemeralAutomationId ? { ephemeralAutomationId } : {}
3774
3909
  };
3775
3910
  if (isOrchestratorThread(from)) {
3776
3911
  patch.parentThreadId = from.id;
@@ -3862,7 +3997,7 @@ async function adoptThread(input) {
3862
3997
  throw new Error(`Worktree not found: ${input.worktreePath}`);
3863
3998
  }
3864
3999
  const repoPath = await resolveRepoRoot(input.worktreePath);
3865
- const { stdout: branch } = await import("./run-PCX5QWR4.js").then(
4000
+ const { stdout: branch } = await import("./run-7QMRYP3F.js").then(
3866
4001
  ({ git: git2 }) => git2(["rev-parse", "--abbrev-ref", "HEAD"], input.worktreePath)
3867
4002
  );
3868
4003
  const thread = createEmptyThread({
@@ -3877,9 +4012,9 @@ async function adoptThread(input) {
3877
4012
  messages: input.messages ?? []
3878
4013
  });
3879
4014
  writeThread(thread);
3880
- const { addWorkspace: addWorkspace2 } = await import("./workspaces-MGKEAYNM.js");
4015
+ const { addWorkspace: addWorkspace2 } = await import("./workspaces-47WQL5IG.js");
3881
4016
  await addWorkspace2(repoPath);
3882
- const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-RXZPTCNH.js");
4017
+ const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-INRDQFWV.js");
3883
4018
  await ensureWorktreeSideboardIgnored(input.worktreePath);
3884
4019
  return thread;
3885
4020
  }
@@ -4371,9 +4506,177 @@ function stackAgentDefaultsFrom(input) {
4371
4506
  };
4372
4507
  }
4373
4508
 
4509
+ // src/git/pr-write.ts
4510
+ import { randomBytes } from "crypto";
4511
+ import { unlinkSync as unlinkSync3, writeFileSync as writeFileSync5 } from "fs";
4512
+ import { tmpdir as tmpdir2 } from "os";
4513
+ import { join as join8 } from "path";
4514
+ async function lookupGithubGraphqlReset(cwd) {
4515
+ const result = await gh(["api", "rate_limit"], cwd, { reject: false });
4516
+ if (result.exitCode !== 0 || !result.stdout.trim()) return void 0;
4517
+ try {
4518
+ const data = JSON.parse(result.stdout);
4519
+ const reset = data.resources?.graphql?.reset;
4520
+ return typeof reset === "number" ? reset : void 0;
4521
+ } catch {
4522
+ return void 0;
4523
+ }
4524
+ }
4525
+ async function formatPrCreateFailure(raw, cwd, ctx) {
4526
+ if (!isGhRateLimitError(raw)) {
4527
+ return formatGhLandError(raw, {
4528
+ targetedRepo: ctx?.slug,
4529
+ headRef: ctx?.head
4530
+ });
4531
+ }
4532
+ const resetAt = await lookupGithubGraphqlReset(cwd);
4533
+ return formatGhLandError(raw, {
4534
+ resetAt,
4535
+ targetedRepo: ctx?.slug,
4536
+ headRef: ctx?.head
4537
+ });
4538
+ }
4539
+ async function createCursorPullRequest(worktreePath, slug, opts) {
4540
+ const bodyText = (opts.body ?? opts.title).trim() || opts.title;
4541
+ const bodyFile = join8(
4542
+ tmpdir2(),
4543
+ `sideboard-pr-body-${process.pid}-${randomBytes(6).toString("hex")}.md`
4544
+ );
4545
+ writeFileSync5(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
4546
+ `, "utf8");
4547
+ try {
4548
+ return await createOrUpdateCursorPr(worktreePath, slug, {
4549
+ title: opts.title,
4550
+ bodyFile,
4551
+ base: opts.base,
4552
+ head: opts.head,
4553
+ draft: opts.draft
4554
+ });
4555
+ } finally {
4556
+ try {
4557
+ unlinkSync3(bodyFile);
4558
+ } catch {
4559
+ }
4560
+ }
4561
+ }
4562
+ function ghPrCreateAssigneeArgs(assignee) {
4563
+ const raw = assignee?.trim();
4564
+ if (raw && /^(none|unassigned)$/i.test(raw)) return [];
4565
+ return ["--assignee", raw || "@me"];
4566
+ }
4567
+ async function createOrUpdatePr(worktreePath, opts) {
4568
+ const origin = await resolveOriginRemote(worktreePath);
4569
+ if (origin?.forge === "entire") throw entireUsesTrails();
4570
+ const cursorSlug = origin?.forge === "cursor" ? origin.slug : null;
4571
+ if (cursorSlug) return createCursorPullRequest(worktreePath, cursorSlug, opts);
4572
+ await ensureGhPreferOrigin(worktreePath);
4573
+ const slug = await resolveGithubRepoSlug(worktreePath);
4574
+ if (!slug) {
4575
+ throw new Error(
4576
+ "Could not resolve the origin GitHub repo (owner/name) for this worktree. Check that `git remote get-url origin` points at github.com."
4577
+ );
4578
+ }
4579
+ const repoArgs = ghRepoSelectArgs(slug);
4580
+ const headRef = ghHeadRef(slug, opts.head);
4581
+ const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
4582
+ const bodyText = clampGithubPrBody(opts.body ?? opts.title);
4583
+ const bodyFile = join8(
4584
+ tmpdir2(),
4585
+ `sideboard-pr-body-${process.pid}-${randomBytes(6).toString("hex")}.md`
4586
+ );
4587
+ writeFileSync5(bodyFile, bodyText.endsWith("\n") ? bodyText : `${bodyText}
4588
+ `, "utf8");
4589
+ const bodyArgs = ["--body-file", bodyFile];
4590
+ try {
4591
+ return await createOrUpdatePrWithBodyFile(worktreePath, {
4592
+ ...opts,
4593
+ slug,
4594
+ repoArgs,
4595
+ headRef,
4596
+ branchOnly,
4597
+ bodyArgs
4598
+ });
4599
+ } finally {
4600
+ try {
4601
+ unlinkSync3(bodyFile);
4602
+ } catch {
4603
+ }
4604
+ }
4605
+ }
4606
+ async function createOrUpdatePrWithBodyFile(worktreePath, opts) {
4607
+ const { slug, repoArgs, headRef, branchOnly, bodyArgs } = opts;
4608
+ const existing = await gh(
4609
+ [...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
4610
+ worktreePath,
4611
+ { reject: false }
4612
+ );
4613
+ if (existing.exitCode === 0 && existing.stdout.trim() && !opts.web) {
4614
+ const url2 = existing.stdout.trim();
4615
+ await gh(
4616
+ [
4617
+ ...repoArgs,
4618
+ "pr",
4619
+ "edit",
4620
+ branchOnly,
4621
+ "--title",
4622
+ opts.title,
4623
+ ...bodyArgs
4624
+ ],
4625
+ worktreePath,
4626
+ { reject: false }
4627
+ );
4628
+ return url2;
4629
+ }
4630
+ if (opts.web) {
4631
+ const args2 = [
4632
+ ...repoArgs,
4633
+ "pr",
4634
+ "create",
4635
+ "--web",
4636
+ "--title",
4637
+ opts.title,
4638
+ ...bodyArgs,
4639
+ "--base",
4640
+ opts.base,
4641
+ "--head",
4642
+ headRef
4643
+ ];
4644
+ if (opts.draft) args2.push("--draft");
4645
+ args2.push(...ghPrCreateAssigneeArgs(opts.assignee));
4646
+ await gh(args2, worktreePath, { reject: false });
4647
+ const again = await gh(
4648
+ [...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
4649
+ worktreePath,
4650
+ { reject: false }
4651
+ );
4652
+ return again.stdout.trim() || "";
4653
+ }
4654
+ const args = [
4655
+ ...repoArgs,
4656
+ "pr",
4657
+ "create",
4658
+ "--title",
4659
+ opts.title,
4660
+ ...bodyArgs,
4661
+ "--base",
4662
+ opts.base,
4663
+ "--head",
4664
+ headRef
4665
+ ];
4666
+ if (opts.draft) args.push("--draft");
4667
+ args.push(...ghPrCreateAssigneeArgs(opts.assignee));
4668
+ const created = await gh(args, worktreePath, { reject: false });
4669
+ if (created.exitCode !== 0) {
4670
+ const raw = created.stderr.trim() || created.stdout.trim() || "gh pr create failed";
4671
+ throw new Error(await formatPrCreateFailure(raw, worktreePath, { slug, head: headRef }));
4672
+ }
4673
+ const url = created.stdout.trim().split("\n").find((l) => l.startsWith("http")) ?? created.stdout.trim();
4674
+ return url;
4675
+ }
4676
+
4374
4677
  // src/diff/diff.ts
4375
- import { existsSync as existsSync9, mkdirSync, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
4376
- import { dirname as dirname2, join as join8 } from "path";
4678
+ import { existsSync as existsSync9, mkdirSync, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
4679
+ import { dirname as dirname2, join as join9 } from "path";
4377
4680
  async function inspectGitWorktree(worktreePath) {
4378
4681
  if (!worktreePath || !existsSync9(worktreePath)) return "missing_worktree";
4379
4682
  const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
@@ -4519,7 +4822,7 @@ new file mode 100644
4519
4822
  };
4520
4823
  }
4521
4824
  async function untrackedPatch(worktreePath, path, maxHunk) {
4522
- const abs = join8(worktreePath, path);
4825
+ const abs = join9(worktreePath, path);
4523
4826
  try {
4524
4827
  const st = statSync2(abs);
4525
4828
  if (st.isFile() && st.size > maxHunk) {
@@ -4991,7 +5294,7 @@ async function getDiff(worktreePath, repoPath, opts) {
4991
5294
  }
4992
5295
  function statWorktreePath(worktreePath, relativePath) {
4993
5296
  assertSafeRelativePath(relativePath);
4994
- const abs = join8(worktreePath, relativePath);
5297
+ const abs = join9(worktreePath, relativePath);
4995
5298
  if (!existsSync9(abs)) return "missing";
4996
5299
  const st = statSync2(abs);
4997
5300
  if (st.isDirectory()) return "dir";
@@ -5033,7 +5336,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
5033
5336
  function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
5034
5337
  assertSafeRelativePath(relativePath);
5035
5338
  const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
5036
- const abs = join8(worktreePath, relativePath);
5339
+ const abs = join9(worktreePath, relativePath);
5037
5340
  const st = statSync2(abs);
5038
5341
  if (!st.isFile()) {
5039
5342
  throw new Error(`Not a file: ${relativePath}`);
@@ -5053,7 +5356,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
5053
5356
  function readWorktreeFile(worktreePath, relativePath, opts) {
5054
5357
  assertSafeRelativePath(relativePath);
5055
5358
  const maxBytes = opts?.maxBytes ?? 2e5;
5056
- const abs = join8(worktreePath, relativePath);
5359
+ const abs = join9(worktreePath, relativePath);
5057
5360
  const st = statSync2(abs);
5058
5361
  if (!st.isFile()) {
5059
5362
  throw new Error(`Not a file: ${relativePath}`);
@@ -5101,9 +5404,9 @@ function assertSafeRelativePath(relativePath) {
5101
5404
  }
5102
5405
  function writeWorktreeFile(worktreePath, relativePath, content) {
5103
5406
  assertSafeRelativePath(relativePath);
5104
- const abs = join8(worktreePath, relativePath);
5407
+ const abs = join9(worktreePath, relativePath);
5105
5408
  mkdirSync(dirname2(abs), { recursive: true });
5106
- writeFileSync5(abs, content, "utf8");
5409
+ writeFileSync6(abs, content, "utf8");
5107
5410
  return { path: relativePath };
5108
5411
  }
5109
5412
  async function getWorktreeDirtyStat(worktreePath) {
@@ -5295,7 +5598,7 @@ async function confirmLand(thread, opts) {
5295
5598
  if (preview.dirty) {
5296
5599
  committed = await commitAll(thread.worktreePath, meta.commitMessage);
5297
5600
  }
5298
- const { git: git2 } = await import("./run-PCX5QWR4.js");
5601
+ const { git: git2 } = await import("./run-7QMRYP3F.js");
5299
5602
  const { stdout: headOut } = await git2(
5300
5603
  ["rev-parse", "--abbrev-ref", "HEAD"],
5301
5604
  thread.worktreePath,
@@ -5326,13 +5629,13 @@ async function confirmLand(thread, opts) {
5326
5629
 
5327
5630
  // src/diff/read-worktree-tail.ts
5328
5631
  import { closeSync, fstatSync, openSync, readSync } from "fs";
5329
- import { join as join9 } from "path";
5632
+ import { join as join10 } from "path";
5330
5633
  var WORKTREE_TAIL_BYTES = 2e5;
5331
5634
  function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TAIL_BYTES) {
5332
5635
  if (!relativePath || relativePath.includes("..") || relativePath.startsWith("/")) {
5333
5636
  throw new Error("Invalid path");
5334
5637
  }
5335
- const abs = join9(worktreePath, relativePath);
5638
+ const abs = join10(worktreePath, relativePath);
5336
5639
  const fd = openSync(abs, "r");
5337
5640
  try {
5338
5641
  const st = fstatSync(fd);
@@ -5366,7 +5669,7 @@ function readWorktreeFileTail(worktreePath, relativePath, maxBytes = WORKTREE_TA
5366
5669
  // src/skills/discover.ts
5367
5670
  import { existsSync as existsSync10, readdirSync as readdirSync3, readFileSync as readFileSync7, statSync as statSync3 } from "fs";
5368
5671
  import { homedir } from "os";
5369
- import { join as join10 } from "path";
5672
+ import { join as join11 } from "path";
5370
5673
 
5371
5674
  // src/skills/bundled/long-running.ts
5372
5675
  var LONG_RUNNING_SKILL_COMMAND = "long-running";
@@ -5535,7 +5838,7 @@ function scanSkillsDir(dir, source, out) {
5535
5838
  }
5536
5839
  for (const entry of entries) {
5537
5840
  if (entry.startsWith(".")) continue;
5538
- const skillMd = join10(dir, entry, "SKILL.md");
5841
+ const skillMd = join11(dir, entry, "SKILL.md");
5539
5842
  if (!existsSync10(skillMd)) continue;
5540
5843
  try {
5541
5844
  if (!statSync3(skillMd).isFile()) continue;
@@ -5557,12 +5860,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
5557
5860
  return;
5558
5861
  }
5559
5862
  if (lookingForSkillsDir && entries.includes("SKILL.md")) {
5560
- const skill = readSkill(join10(dir, "SKILL.md"), "cli");
5863
+ const skill = readSkill(join11(dir, "SKILL.md"), "cli");
5561
5864
  if (skill) out.push(skill);
5562
5865
  }
5563
5866
  for (const entry of entries) {
5564
5867
  if (entry === "node_modules" || entry === ".git") continue;
5565
- const full = join10(dir, entry);
5868
+ const full = join11(dir, entry);
5566
5869
  try {
5567
5870
  if (!statSync3(full).isDirectory()) continue;
5568
5871
  } catch {
@@ -5582,17 +5885,17 @@ function discoverSkills(worktreePath) {
5582
5885
  const home = homedir();
5583
5886
  const collected = [];
5584
5887
  for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
5585
- scanSkillsDir(join10(worktreePath, rel), "workspace", collected);
5888
+ scanSkillsDir(join11(worktreePath, rel), "workspace", collected);
5586
5889
  }
5587
5890
  for (const abs of [
5588
- join10(home, ".claude/skills"),
5589
- join10(home, ".cursor/skills"),
5590
- join10(home, ".sideboard/skills"),
5591
- join10(home, ".brightsy/skills")
5891
+ join11(home, ".claude/skills"),
5892
+ join11(home, ".cursor/skills"),
5893
+ join11(home, ".sideboard/skills"),
5894
+ join11(home, ".brightsy/skills")
5592
5895
  ]) {
5593
5896
  scanSkillsDir(abs, "user", collected);
5594
5897
  }
5595
- scanClaudePluginSkills(join10(home, ".claude/plugins"), collected);
5898
+ scanClaudePluginSkills(join11(home, ".claude/plugins"), collected);
5596
5899
  collected.push(...bundledSkills());
5597
5900
  const rank = {
5598
5901
  workspace: 0,
@@ -5820,7 +6123,7 @@ function promptForJoinedSteer(input) {
5820
6123
  rewriteTrailingUserPrompt(input.threadId, input.promptText, input.latestPrompt);
5821
6124
  const { agentPrompt: expandedLatest } = expandComposerPrompt(
5822
6125
  input.worktreePath,
5823
- expandCanonicalGitRequest(input.latestPrompt),
6126
+ expandCanonicalGitRequest(input.latestPrompt, { forge: input.gitForge }),
5824
6127
  { attachments: input.attachments }
5825
6128
  );
5826
6129
  return input.expandedPrompt && input.agentPrompt.endsWith(input.expandedPrompt) ? input.agentPrompt.slice(0, -input.expandedPrompt.length) + expandedLatest : `${input.agentPrompt}
@@ -5916,11 +6219,33 @@ async function enqueueThreadSend(host, threadRef, prompt, opts) {
5916
6219
 
5917
6220
  // src/agents/instructions.ts
5918
6221
  import { existsSync as existsSync12 } from "fs";
5919
- import { join as join12 } from "path";
6222
+ import { join as join13 } from "path";
6223
+
6224
+ // src/agents/forge-git-directives.ts
6225
+ function formatCursorGitDirective(slug) {
6226
+ const repo = slug?.trim() || "<origin-owner/name>";
6227
+ return [
6228
+ `Git host (Settings \u2192 Git \u2192 Cursor): this checkout is on Cursor (\`origin.cursor.com\`, \`${repo}\`).`,
6229
+ "- Use the `origin` CLI, not `gh`. Where commands overlap, flags follow `gh` (`origin <command> --help`).",
6230
+ "- `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.",
6231
+ "- 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.",
6232
+ "- Origin has no issue tracker. Tickets for this repo come from Linear or AbleTime via `list_issues`. Do not use `gh issue`."
6233
+ ].join("\n");
6234
+ }
6235
+ function formatEntireGitDirective(slug) {
6236
+ const repo = slug?.trim() || "<origin-owner/name>";
6237
+ return [
6238
+ `Git host (Settings \u2192 Git \u2192 Entire): this checkout is on Entire (\`${repo}\`).`,
6239
+ "- Use the `entire` CLI, not `gh` or `origin`. Trails replace pull requests and GitHub issues.",
6240
+ "- `entire` uses the login from Settings \u2192 Git \u2192 Entire. Do not read tokens, set `ENTIRE_TOKEN`, or run `entire login` from this turn.",
6241
+ "- 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.",
6242
+ "- Tickets for this repo are Trails (`entire trail list` / `entire trail show`). Do not use `gh issue`."
6243
+ ].join("\n");
6244
+ }
5920
6245
 
5921
6246
  // src/skills/detached-job-path.ts
5922
6247
  import { existsSync as existsSync11 } from "fs";
5923
- import { dirname as dirname3, join as join11 } from "path";
6248
+ import { dirname as dirname3, join as join12 } from "path";
5924
6249
  import { fileURLToPath } from "url";
5925
6250
  var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
5926
6251
  function compiledModuleDir() {
@@ -5937,7 +6262,7 @@ function compiledModuleDir() {
5937
6262
  }
5938
6263
  function detachedJobScriptIn(dir) {
5939
6264
  for (const name of DETACHED_JOB_FILENAMES) {
5940
- const script = join11(dir, "scripts", name);
6265
+ const script = join12(dir, "scripts", name);
5941
6266
  if (existsSync11(script)) return script;
5942
6267
  }
5943
6268
  return null;
@@ -6047,17 +6372,35 @@ function formatWorktreeDirective(thread, opts) {
6047
6372
  lines.push(
6048
6373
  "- 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)."
6049
6374
  );
6050
- lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
6375
+ const cursorRepo = opts?.originForge === "cursor";
6376
+ const entireRepo = opts?.originForge === "entire";
6377
+ if (cursorRepo) {
6378
+ lines.push(formatCursorGitDirective(opts?.originSlug));
6379
+ } else if (entireRepo) {
6380
+ lines.push(formatEntireGitDirective(opts?.originSlug));
6381
+ } else {
6382
+ lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
6383
+ }
6051
6384
  lines.push(
6052
6385
  "- 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."
6053
6386
  );
6054
6387
  lines.push(
6055
- "- 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`)."
6388
+ 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`)."
6056
6389
  );
6057
6390
  if (thread.prUrl) {
6058
6391
  lines.push(
6059
6392
  `- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
6060
6393
  );
6394
+ } else if (entireRepo) {
6395
+ lines.push(
6396
+ '- 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`.'
6397
+ );
6398
+ } else if (cursorRepo) {
6399
+ const slug = opts?.originSlug?.trim() || "<origin-owner/name>";
6400
+ const resolve = opts?.originSlug?.trim() ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
6401
+ lines.push(
6402
+ `- 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\`.`
6403
+ );
6061
6404
  } else {
6062
6405
  const slug = opts?.githubSlug ?? "<origin-owner/name>";
6063
6406
  const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
@@ -6072,7 +6415,7 @@ function formatWorktreeDirective(thread, opts) {
6072
6415
  lines.push(formatDevAccessHint(opts?.activeRuns));
6073
6416
  lines.push("");
6074
6417
  lines.push(
6075
- "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."
6418
+ "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."
6076
6419
  );
6077
6420
  lines.push(
6078
6421
  "`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
@@ -6092,7 +6435,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
6092
6435
  return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
6093
6436
  }
6094
6437
  function formatWorktreeReminder() {
6095
- 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).";
6438
+ 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).";
6096
6439
  }
6097
6440
  function formatClaudeSubagentReminder() {
6098
6441
  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.';
@@ -6200,9 +6543,9 @@ function formatPrGateDirective() {
6200
6543
  }
6201
6544
  function formatProcessGuideDirective(opts) {
6202
6545
  const worktree = opts?.worktreePath?.trim();
6203
- const hasGraphSkill = !!worktree && existsSync12(join12(worktree, ".claude/skills/graph-engineering/SKILL.md"));
6204
- const hasReviewSkill = !!worktree && existsSync12(join12(worktree, ".claude/skills/review/SKILL.md"));
6205
- const hasInstallSkill = !!worktree && existsSync12(join12(worktree, ".claude/skills/worktree-install/SKILL.md"));
6546
+ const hasGraphSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/graph-engineering/SKILL.md"));
6547
+ const hasReviewSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/review/SKILL.md"));
6548
+ const hasInstallSkill = !!worktree && existsSync12(join13(worktree, ".claude/skills/worktree-install/SKILL.md"));
6206
6549
  return [
6207
6550
  "Process guides (recurring work only):",
6208
6551
  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,
@@ -6356,6 +6699,7 @@ function compactIssueRow(issue, opts) {
6356
6699
  function formatMcpIssueList(input) {
6357
6700
  const truncated = input.truncated || Boolean(input.commentsTruncated);
6358
6701
  const comments = input.comments ?? [];
6702
+ 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;
6359
6703
  return {
6360
6704
  ...input.source ? { source: input.source } : {},
6361
6705
  ...input.viewer ? { viewer: input.viewer } : {},
@@ -6363,9 +6707,8 @@ function formatMcpIssueList(input) {
6363
6707
  returned: input.issues.length,
6364
6708
  truncated,
6365
6709
  ...input.since ? { since: input.since } : {},
6366
- ...truncated ? {
6367
- 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."
6368
- } : {},
6710
+ ...input.unavailableReason ? { unavailableReason: input.unavailableReason } : {},
6711
+ ...pageHint ? { hint: pageHint } : {},
6369
6712
  issues: input.issues.map((issue) => compactIssueRow(issue, { since: input.since })),
6370
6713
  ...input.since || comments.length > 0 ? { comments } : {}
6371
6714
  };
@@ -6382,7 +6725,8 @@ function formatListedIssuesForMcp(result, page) {
6382
6725
  truncated: windowed.truncated,
6383
6726
  since: result.since,
6384
6727
  comments: commentWindow.items,
6385
- commentsTruncated: commentWindow.truncated
6728
+ commentsTruncated: commentWindow.truncated,
6729
+ unavailableReason: result.unavailableReason
6386
6730
  });
6387
6731
  }
6388
6732
  function mcpJson(payload, isError = false) {
@@ -6710,7 +7054,7 @@ async function syncThreadBranchFromGit(threadId) {
6710
7054
  // src/store/schedules.ts
6711
7055
  import { randomUUID as randomUUID4 } from "crypto";
6712
7056
  import { existsSync as existsSync13, readFileSync as readFileSync8 } from "fs";
6713
- import { join as join13 } from "path";
7057
+ import { join as join14 } from "path";
6714
7058
  import { Cron } from "croner";
6715
7059
  var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
6716
7060
  var UNIT_MS = {
@@ -6720,7 +7064,7 @@ var UNIT_MS = {
6720
7064
  d: 864e5
6721
7065
  };
6722
7066
  function schedulesPath() {
6723
- return join13(appDataDir(), "schedules.json");
7067
+ return join14(appDataDir(), "schedules.json");
6724
7068
  }
6725
7069
  function parseDurationMs(every) {
6726
7070
  const m = every.trim().match(DURATION_RE);
@@ -6732,7 +7076,7 @@ function parseDurationMs(every) {
6732
7076
  }
6733
7077
  function defaultScheduleName(prompt) {
6734
7078
  const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
6735
- if (!line) return "Untitled schedule";
7079
+ if (!line) return "Untitled automation";
6736
7080
  return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
6737
7081
  }
6738
7082
  function resolveScheduleThreadId(raw, env = process.env) {
@@ -6803,6 +7147,45 @@ function normalizeWhen(raw) {
6803
7147
  }
6804
7148
  throw new Error("Schedule `when` must be once, every, or cron");
6805
7149
  }
7150
+ var ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
7151
+ "transcript",
7152
+ "file",
7153
+ "issue",
7154
+ "workspace",
7155
+ "diff-comment",
7156
+ "code-ref"
7157
+ ]);
7158
+ function normalizeOptionalBool(raw) {
7159
+ if (raw === true || raw === false) return raw;
7160
+ return null;
7161
+ }
7162
+ function normalizeAutonomy(raw) {
7163
+ return raw === "default" || raw === "full" ? raw : null;
7164
+ }
7165
+ function normalizeAttachments(raw) {
7166
+ if (!Array.isArray(raw)) return [];
7167
+ const out = [];
7168
+ for (const item of raw) {
7169
+ if (!item || typeof item !== "object") continue;
7170
+ const row = item;
7171
+ if (typeof row.id !== "string" || !row.id.trim()) continue;
7172
+ if (typeof row.name !== "string" || !row.name) continue;
7173
+ if (typeof row.content !== "string") continue;
7174
+ if (!ATTACHMENT_KINDS.has(row.kind)) continue;
7175
+ const next = {
7176
+ id: row.id,
7177
+ name: row.name,
7178
+ kind: row.kind,
7179
+ content: row.content
7180
+ };
7181
+ if (typeof row.path === "string" && row.path) next.path = row.path;
7182
+ if (typeof row.previewDataUrl === "string" && row.previewDataUrl) {
7183
+ next.previewDataUrl = row.previewDataUrl;
7184
+ }
7185
+ out.push(next);
7186
+ }
7187
+ return out;
7188
+ }
6806
7189
  function normalizeTask(raw) {
6807
7190
  const when = normalizeWhen(raw.when);
6808
7191
  const agent = raw.agent && isOrchestratorCapableAgent(raw.agent) ? raw.agent : null;
@@ -6815,6 +7198,11 @@ function normalizeTask(raw) {
6815
7198
  threadId: raw.threadId?.trim() || null,
6816
7199
  agent,
6817
7200
  model: raw.model?.trim() || null,
7201
+ effort: normalizeThinkingEffort(raw.effort),
7202
+ fast: normalizeOptionalBool(raw.fast),
7203
+ planMode: normalizeOptionalBool(raw.planMode),
7204
+ autonomy: normalizeAutonomy(raw.autonomy),
7205
+ attachments: normalizeAttachments(raw.attachments),
6818
7206
  nextRunAt: raw.nextRunAt,
6819
7207
  lastRunAt: raw.lastRunAt ?? null,
6820
7208
  lastThreadId: raw.lastThreadId ?? null,
@@ -6861,6 +7249,11 @@ function buildTask(input, now) {
6861
7249
  threadId: input.threadId?.trim() || null,
6862
7250
  agent,
6863
7251
  model: input.model?.trim() || null,
7252
+ effort: input.effort != null ? normalizeThinkingEffort(input.effort) : null,
7253
+ fast: normalizeOptionalBool(input.fast),
7254
+ planMode: normalizeOptionalBool(input.planMode),
7255
+ autonomy: normalizeAutonomy(input.autonomy),
7256
+ attachments: normalizeAttachments(input.attachments),
6864
7257
  nextRunAt,
6865
7258
  lastRunAt: null,
6866
7259
  lastThreadId: null,
@@ -6905,7 +7298,7 @@ function createSchedule(input) {
6905
7298
  function updateSchedule(id, patch) {
6906
7299
  const rows = readAll();
6907
7300
  const idx = rows.findIndex((row) => row.id === id || id.length >= 8 && row.id.startsWith(id));
6908
- if (idx < 0) throw new Error(`Schedule not found: ${id}`);
7301
+ if (idx < 0) throw new Error(`Automation not found: ${id}`);
6909
7302
  const prev = rows[idx];
6910
7303
  const when = patch.when ? normalizeWhen(patch.when) : prev.when;
6911
7304
  const prompt = patch.prompt !== void 0 ? patch.prompt.trim() : prev.prompt;
@@ -6920,6 +7313,11 @@ function updateSchedule(id, patch) {
6920
7313
  threadId: patch.threadId !== void 0 ? patch.threadId?.trim() || null : prev.threadId,
6921
7314
  agent: patch.agent !== void 0 ? patch.agent ? coerceOrchestratorAgent(patch.agent) : null : prev.agent,
6922
7315
  model: patch.model !== void 0 ? patch.model?.trim() || null : prev.model,
7316
+ effort: patch.effort !== void 0 ? normalizeThinkingEffort(patch.effort) : prev.effort,
7317
+ fast: patch.fast !== void 0 ? normalizeOptionalBool(patch.fast) : prev.fast,
7318
+ planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
7319
+ autonomy: patch.autonomy !== void 0 ? normalizeAutonomy(patch.autonomy) : prev.autonomy,
7320
+ attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
6923
7321
  nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
6924
7322
  lastError: whenChanged ? null : prev.lastError,
6925
7323
  updatedAt: nowIso()
@@ -6934,13 +7332,13 @@ function deleteSchedule(id) {
6934
7332
  const next = rows.filter(
6935
7333
  (row) => row.id !== id && !(id.length >= 8 && row.id.startsWith(id))
6936
7334
  );
6937
- if (next.length === rows.length) throw new Error(`Schedule not found: ${id}`);
7335
+ if (next.length === rows.length) throw new Error(`Automation not found: ${id}`);
6938
7336
  writeAll(next);
6939
7337
  }
6940
7338
  function recordScheduleRun(id, result) {
6941
7339
  const rows = readAll();
6942
7340
  const idx = rows.findIndex((row) => row.id === id);
6943
- if (idx < 0) throw new Error(`Schedule not found: ${id}`);
7341
+ if (idx < 0) throw new Error(`Automation not found: ${id}`);
6944
7342
  const prev = rows[idx];
6945
7343
  const firedAt = result.firedAt ?? /* @__PURE__ */ new Date();
6946
7344
  const next = {
@@ -6967,21 +7365,56 @@ function formatScheduledPrompt(name, prompt) {
6967
7365
  ${prompt}`;
6968
7366
  }
6969
7367
  async function defaultDeps() {
6970
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-NCA4LSCC.js");
7368
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-B4STIW4B.js");
6971
7369
  const orch = getOrchestrator2();
6972
7370
  return {
6973
7371
  findThread: (id) => findThreadByRef(id),
6974
- send: (id, prompt) => orch.send(id, prompt),
7372
+ send: async (id, prompt, opts) => {
7373
+ if (opts?.options && Object.keys(opts.options).length > 0) {
7374
+ try {
7375
+ orch.setThreadOptions(id, opts.options);
7376
+ } catch {
7377
+ const rest = scheduleOptionsAfterRefusedAgentSwitch(opts.options);
7378
+ if (Object.keys(rest).length > 0) {
7379
+ try {
7380
+ orch.setThreadOptions(id, rest);
7381
+ } catch {
7382
+ }
7383
+ }
7384
+ }
7385
+ }
7386
+ const thread = findThreadByRef(id);
7387
+ const attachments = thread ? persistPendingFileAttachments(thread.worktreePath, opts?.attachments ?? []) : opts?.attachments ?? [];
7388
+ return orch.send(id, prompt, { attachments });
7389
+ },
6975
7390
  startOrchestration: (opts) => startOrchestration2(opts)
6976
7391
  };
6977
7392
  }
7393
+ function scheduleOptionsAfterRefusedAgentSwitch(options) {
7394
+ const { agent: _agent, model: _model, ...rest } = options;
7395
+ return rest;
7396
+ }
7397
+ function scheduleSendOptions(schedule) {
7398
+ const patch = {};
7399
+ if (schedule.agent) {
7400
+ patch.agent = schedule.agent;
7401
+ patch.model = schedule.model;
7402
+ } else if (schedule.model) {
7403
+ patch.model = schedule.model;
7404
+ }
7405
+ if (schedule.effort) patch.effort = schedule.effort;
7406
+ if (schedule.fast != null) patch.fast = schedule.fast;
7407
+ if (schedule.planMode != null) patch.planMode = schedule.planMode;
7408
+ if (schedule.autonomy) patch.autonomy = schedule.autonomy;
7409
+ return Object.keys(patch).length > 0 ? patch : void 0;
7410
+ }
6978
7411
  function pickAgent(schedule) {
6979
7412
  if (schedule.agent) return schedule.agent;
6980
7413
  return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
6981
7414
  }
6982
7415
  async function fireSchedule(id) {
6983
7416
  const schedule = getSchedule(id);
6984
- if (!schedule) throw new Error(`Schedule not found: ${id}`);
7417
+ if (!schedule) throw new Error(`Automation not found: ${id}`);
6985
7418
  if (firing.has(schedule.id)) return schedule;
6986
7419
  firing.add(schedule.id);
6987
7420
  try {
@@ -6989,18 +7422,28 @@ async function fireSchedule(id) {
6989
7422
  const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
6990
7423
  const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
6991
7424
  if (target && target.status !== "archived") {
6992
- const sent = await deps.send(target.id, prompt);
7425
+ const sent = await deps.send(target.id, prompt, {
7426
+ attachments: schedule.attachments,
7427
+ options: scheduleSendOptions(schedule)
7428
+ });
6993
7429
  return recordScheduleRun(schedule.id, {
6994
7430
  lastThreadId: sent.id,
6995
7431
  lastError: null
6996
7432
  });
6997
7433
  }
7434
+ const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
6998
7435
  const created = await deps.startOrchestration({
6999
7436
  goal: prompt,
7000
7437
  agent: pickAgent(schedule),
7001
- model: schedule.model
7438
+ model: schedule.model,
7439
+ ...schedule.effort ? { effort: schedule.effort } : {},
7440
+ ...schedule.fast != null ? { fast: schedule.fast } : {},
7441
+ ...schedule.planMode != null ? { planMode: schedule.planMode } : {},
7442
+ ...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
7443
+ attachments: schedule.attachments,
7444
+ ...pinReplacement ? {} : { ephemeralAutomationId: schedule.id, ephemeralTitle: schedule.name }
7002
7445
  });
7003
- if (schedule.threadId && schedule.when.kind !== "once") {
7446
+ if (pinReplacement) {
7004
7447
  updateSchedule(schedule.id, { threadId: created.id });
7005
7448
  }
7006
7449
  return recordScheduleRun(schedule.id, {
@@ -7288,7 +7731,7 @@ var Orchestrator = class {
7288
7731
  orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
7289
7732
  });
7290
7733
  }
7291
- const { autoCleanupOrphansEnabled } = await import("./app-settings-V6YPYY57.js");
7734
+ const { autoCleanupOrphansEnabled } = await import("./app-settings-P3H4SEIK.js");
7292
7735
  if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
7293
7736
  await cleanupOrphanWorktrees({ repoPaths });
7294
7737
  }
@@ -7682,7 +8125,7 @@ var Orchestrator = class {
7682
8125
  }
7683
8126
  await setup;
7684
8127
  if (skipSetup) return;
7685
- const { autoRunAfterSetupEnabled } = await import("./app-settings-V6YPYY57.js");
8128
+ const { autoRunAfterSetupEnabled } = await import("./app-settings-P3H4SEIK.js");
7686
8129
  if (autoRunAfterSetupEnabled()) {
7687
8130
  try {
7688
8131
  await this.startDev(threadId);
@@ -7891,6 +8334,7 @@ var Orchestrator = class {
7891
8334
  } finally {
7892
8335
  this.draining.delete(threadId);
7893
8336
  }
8337
+ await archiveEphemeralAutomationIfReady(threadId, (id) => this.archive(id));
7894
8338
  }
7895
8339
  async runTurn(threadId, prompt) {
7896
8340
  const existing = readThread(threadId);
@@ -7974,7 +8418,8 @@ var Orchestrator = class {
7974
8418
  return;
7975
8419
  }
7976
8420
  thread = this.requireThread(threadId);
7977
- const gitPrompt = expandCanonicalGitRequest(promptText);
8421
+ const turnOrigin = thread.worktreePath?.trim() ? await resolveOriginRemote(thread.worktreePath).catch(() => null) : null;
8422
+ const gitPrompt = expandCanonicalGitRequest(promptText, { forge: turnOrigin?.forge });
7978
8423
  const { agentPrompt: expandedPrompt } = expandComposerPrompt(
7979
8424
  thread.worktreePath,
7980
8425
  gitPrompt,
@@ -8058,14 +8503,12 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
8058
8503
  }
8059
8504
  const isBrightsy = fresh.agent === "brightsy";
8060
8505
  const isOrchestration = isOrchestratorThread(fresh);
8061
- const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-V6YPYY57.js");
8506
+ const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-P3H4SEIK.js");
8062
8507
  const gitAuthMode = getGithubGitAuthMode();
8063
8508
  const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
8064
- githubSlug: await withTimeout(
8065
- resolveGithubRepoSlug(fresh.worktreePath),
8066
- 8e3,
8067
- "resolveGithubRepoSlug"
8068
- ).catch(() => null),
8509
+ githubSlug: turnOrigin?.forge === "github" ? turnOrigin.slug : await withTimeout(resolveGithubRepoSlug(fresh.worktreePath), 8e3, "resolveGithubRepoSlug").catch(() => null),
8510
+ originForge: turnOrigin?.forge ?? null,
8511
+ originSlug: turnOrigin?.slug ?? null,
8069
8512
  gitAuthMode,
8070
8513
  activeRuns: annotateDevAccessRuns(
8071
8514
  mergeWorktreeActiveRuns(
@@ -8158,7 +8601,8 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
8158
8601
  agentPrompt,
8159
8602
  expandedPrompt,
8160
8603
  worktreePath: fresh.worktreePath,
8161
- attachments: autoContinue ? [] : sentAttachments ?? []
8604
+ attachments: autoContinue ? [] : sentAttachments ?? [],
8605
+ gitForge: turnOrigin?.forge
8162
8606
  });
8163
8607
  const handle = await spawnAgentTurn(
8164
8608
  fresh,
@@ -9386,7 +9830,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9386
9830
  if (Object.keys(patch).length === 0) continue;
9387
9831
  updateThread(t.id, patch);
9388
9832
  }
9389
- const { autoArchiveOnMergeEnabled } = await import("./app-settings-V6YPYY57.js");
9833
+ const { autoArchiveOnMergeEnabled } = await import("./app-settings-P3H4SEIK.js");
9390
9834
  const latest = this.requireThread(thread.id);
9391
9835
  if (!shouldAutoArchiveOnPrMerge({
9392
9836
  previousPrState: prevState || null,
@@ -9710,7 +10154,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9710
10154
  await runArchiveScript(thread.repoPath, thread.worktreePath);
9711
10155
  } catch {
9712
10156
  }
9713
- const { deleteBranchOnPurgeEnabled } = await import("./app-settings-V6YPYY57.js");
10157
+ const { deleteBranchOnPurgeEnabled } = await import("./app-settings-P3H4SEIK.js");
9714
10158
  const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
9715
10159
  await removeWorktree(thread.repoPath, thread.worktreePath, {
9716
10160
  deleteBranch: deleteBranch ? thread.branchName : void 0
@@ -9724,6 +10168,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9724
10168
  if (thread.status !== "archived") {
9725
10169
  throw new Error("Thread is not archived");
9726
10170
  }
10171
+ clearEphemeralAutomation(thread.id);
9727
10172
  if (isGlobalThread(thread)) {
9728
10173
  const { globalAgentCwd } = await import("./paths-PHWEVXD5.js");
9729
10174
  updateThread(thread.id, { worktreePath: globalAgentCwd() });
@@ -9741,7 +10186,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
9741
10186
  await withRepoGitLock(thread.repoPath, async () => {
9742
10187
  await git(["worktree", "add", dest, thread.branchName], thread.repoPath);
9743
10188
  });
9744
- const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-RXZPTCNH.js");
10189
+ const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-INRDQFWV.js");
9745
10190
  await ensureWorktreeSideboardIgnored(dest);
9746
10191
  }
9747
10192
  const restorePatch = {};
@@ -9823,10 +10268,11 @@ async function startOrchestration(opts) {
9823
10268
  planMode: opts.planMode,
9824
10269
  attachments: opts.attachments
9825
10270
  });
10271
+ const ready2 = markEphemeralAutomation(thread2.id, opts);
9826
10272
  if (goal) {
9827
- return orch.send(thread2.id, goal);
10273
+ return orch.send(ready2.id, goal);
9828
10274
  }
9829
- return thread2;
10275
+ return ready2;
9830
10276
  }
9831
10277
  const { titleFromPrompt: titleFromPrompt2 } = await import("./title-Z7WAJN57.js");
9832
10278
  const title = titleFromPrompt2(goal) || "Orchestration";
@@ -9846,7 +10292,7 @@ async function startOrchestration(opts) {
9846
10292
  sourceRef: "default",
9847
10293
  ...createOpts
9848
10294
  }).catch(async () => {
9849
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-THAXW5U7.js");
10295
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-PDNPL5CQ.js");
9850
10296
  const repo = await resolveRepoRoot2(repoPath);
9851
10297
  const def = await resolveDefaultBranch2(repo);
9852
10298
  return orch.createThread({
@@ -9856,15 +10302,16 @@ async function startOrchestration(opts) {
9856
10302
  repoPath: repo
9857
10303
  });
9858
10304
  });
9859
- const { updateThread: upd } = await import("./thread-store-7BBA63KV.js");
10305
+ const { updateThread: upd } = await import("./thread-store-JRSL4HQY.js");
9860
10306
  const updated = upd(thread.id, {
9861
10307
  sourceType: "orchestration",
9862
10308
  sourceRef: goal
9863
10309
  });
10310
+ const ready = markEphemeralAutomation(updated.id, opts);
9864
10311
  if (goal) {
9865
- return orch.send(updated.id, goal);
10312
+ return orch.send(ready.id, goal);
9866
10313
  }
9867
- return updated;
10314
+ return ready;
9868
10315
  }
9869
10316
 
9870
10317
  export {
@@ -9996,6 +10443,8 @@ export {
9996
10443
  initStackFromThread,
9997
10444
  createPrStack,
9998
10445
  stackAgentDefaultsFrom,
10446
+ ghPrCreateAssigneeArgs,
10447
+ createOrUpdatePr,
9999
10448
  inspectGitWorktree,
10000
10449
  initializeGitRepository,
10001
10450
  captureTurnBaseline,
@@ -10028,6 +10477,8 @@ export {
10028
10477
  moveQueuedItemToFront,
10029
10478
  shiftQueuedItem,
10030
10479
  resolveSendFollowUp,
10480
+ formatCursorGitDirective,
10481
+ formatEntireGitDirective,
10031
10482
  packagedDetachedJobPath,
10032
10483
  resolveDetachedJobScript,
10033
10484
  formatDetachedJobInvoke,