@sideboard-ai/core 0.1.145 → 0.1.146

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 (31) hide show
  1. package/dist/{agents-4WOO4WN4.js → agents-N3KMRQUZ.js} +4 -4
  2. package/dist/{agents-VFBNZHI4.js → agents-YVETHB2R.js} +4 -4
  3. package/dist/{chunk-TTJ6EYZC.js → chunk-4RYRNJPN.js} +3 -3
  4. package/dist/{chunk-2C5RE7K4.js → chunk-67K3FRKR.js} +1 -1
  5. package/dist/{chunk-G3KLNP2B.js → chunk-IHSR7EVK.js} +2 -2
  6. package/dist/{chunk-3UD2LW4P.js → chunk-JHZ6HGRI.js} +2 -2
  7. package/dist/{chunk-QS5JJ2IM.js → chunk-JTPDWTWJ.js} +117 -34
  8. package/dist/{chunk-LWRNRMYY.js → chunk-JW436RTA.js} +2 -2
  9. package/dist/{chunk-XUYIJY6D.js → chunk-KNE3FZ46.js} +2 -2
  10. package/dist/{chunk-335KQKWX.js → chunk-KZG47SZP.js} +18 -14
  11. package/dist/{chunk-DN7UA3UT.js → chunk-SXPTL222.js} +1 -1
  12. package/dist/{chunk-UJWGZM4K.js → chunk-WWH4NNBH.js} +3 -3
  13. package/dist/{chunk-JSYIBLBK.js → chunk-YP3CSOZ6.js} +117 -34
  14. package/dist/{chunk-3EMJ5LVV.js → chunk-ZZBN2MR7.js} +18 -14
  15. package/dist/{coordinator-prompt-JSX22ULD.js → coordinator-prompt-2EOR35TP.js} +2 -2
  16. package/dist/{coordinator-prompt-J2WBXGLP.js → coordinator-prompt-6EPVHVGJ.js} +2 -2
  17. package/dist/{global-workspace-6WR7OGMI.js → global-workspace-EZVQPMWT.js} +3 -3
  18. package/dist/{global-workspace-AQESFS7I.js → global-workspace-PANZGRUS.js} +3 -3
  19. package/dist/index.cjs +125 -34
  20. package/dist/index.d.cts +23 -1
  21. package/dist/index.d.ts +23 -1
  22. package/dist/index.js +12 -6
  23. package/dist/mcp/run-stdio.cjs +119 -34
  24. package/dist/mcp/run-stdio.js +6 -6
  25. package/dist/{orchestrator-XPGJV7JK.js → orchestrator-KWV2PPML.js} +6 -6
  26. package/dist/{orchestrator-WWQBBIPP.js → orchestrator-T35BJZWY.js} +6 -6
  27. package/dist/{workspaces-V3RNE5ZX.js → workspaces-DWERPUQJ.js} +4 -4
  28. package/dist/{workspaces-WALT3MJB.js → workspaces-ZJATBC4A.js} +4 -4
  29. package/dist/{worktree-3NLPMA7K.js → worktree-RZRJNHYL.js} +7 -1
  30. package/dist/{worktree-TUZX7F7P.js → worktree-UCWWTVLS.js} +7 -1
  31. package/package.json +1 -1
@@ -2252,45 +2252,128 @@ async function resolveWorktreeStartPoint(repoPath, sourceRef) {
2252
2252
  function isLocalPrFetchBranch(ref) {
2253
2253
  return /^sideboard-pr-\d+$/.test(ref.trim());
2254
2254
  }
2255
- async function createThreadWorktree(opts) {
2256
- let branchName = `thread/${opts.slug}`;
2257
- const worktreePath = join2(worktreesRoot(opts.repoPath), opts.slug);
2258
- if (existsSync2(worktreePath)) {
2259
- throw new Error(`Worktree already exists at ${worktreePath}`);
2255
+ function originFetchBranch(sourceRef) {
2256
+ const ref = sourceRef.trim();
2257
+ if (!ref || isLocalPrFetchBranch(ref)) return null;
2258
+ if (ref.startsWith("refs/remotes/origin/")) {
2259
+ return ref.slice("refs/remotes/origin/".length) || null;
2260
2260
  }
2261
- await ensureGhPreferOrigin(opts.repoPath);
2262
- let startPoint = null;
2261
+ if (ref.startsWith("refs/heads/")) {
2262
+ return ref.slice("refs/heads/".length) || null;
2263
+ }
2264
+ if (ref.startsWith("refs/")) return null;
2265
+ if (ref.startsWith("origin/")) return ref.slice("origin/".length) || null;
2266
+ return ref;
2267
+ }
2268
+ async function fetchOriginWithAuth(repoPath, args, timeoutMs) {
2269
+ const first = await git(args, repoPath, { reject: false, timeoutMs });
2270
+ if (first.exitCode === 0) return true;
2271
+ let mode;
2263
2272
  try {
2264
- startPoint = await resolveWorktreeStartPoint(opts.repoPath, opts.sourceRef);
2273
+ mode = getGithubGitAuthMode();
2265
2274
  } catch {
2266
- startPoint = null;
2275
+ return false;
2267
2276
  }
2268
- if (!isLocalPrFetchBranch(opts.sourceRef)) {
2269
- const fetchTimeoutMs = startPoint ? 12e3 : 45e3;
2270
- await git(["fetch", "origin", "--prune"], opts.repoPath, {
2271
- reject: false,
2272
- timeoutMs: fetchTimeoutMs
2277
+ if (mode === "ssh") return false;
2278
+ const token = await resolveGithubAgentToken(mode, repoPath);
2279
+ if (!token) return false;
2280
+ const tryHttps = async (header) => git(args, repoPath, {
2281
+ reject: false,
2282
+ timeoutMs,
2283
+ env: { GIT_TERMINAL_PROMPT: "0" },
2284
+ config: {
2285
+ "url.https://github.com/.insteadOf": "git@github.com:",
2286
+ "http.extraHeader": header
2287
+ }
2288
+ });
2289
+ const bearer = await tryHttps(`AUTHORIZATION: bearer ${token}`);
2290
+ if (bearer.exitCode === 0) return true;
2291
+ const basic = Buffer.from(`x-access-token:${token}`, "utf8").toString("base64");
2292
+ const basicFetch = await tryHttps(`Authorization: Basic ${basic}`);
2293
+ return basicFetch.exitCode === 0;
2294
+ }
2295
+ async function fetchOriginForWorktree(repoPath, sourceRef, opts) {
2296
+ const timeoutMs = opts?.timeoutMs ?? 2e4;
2297
+ const branch = originFetchBranch(sourceRef);
2298
+ if (!branch) return false;
2299
+ const tipOk = await fetchOriginWithAuth(
2300
+ repoPath,
2301
+ ["fetch", "origin", branch],
2302
+ timeoutMs
2303
+ );
2304
+ await fetchOriginWithAuth(repoPath, ["fetch", "origin", "--prune"], timeoutMs);
2305
+ return tipOk;
2306
+ }
2307
+ async function fastForwardMainCheckoutIfSafe(repoPath, opts) {
2308
+ try {
2309
+ const branch = opts?.branch?.trim() || await resolveDefaultBranch(repoPath, { network: false });
2310
+ const head = await git(["rev-parse", "--abbrev-ref", "HEAD"], repoPath, {
2311
+ reject: false
2273
2312
  });
2274
- if (!opts.sourceRef.startsWith("origin/") && !opts.sourceRef.startsWith("refs/")) {
2275
- await git(["fetch", "origin", opts.sourceRef], opts.repoPath, {
2276
- reject: false,
2277
- timeoutMs: fetchTimeoutMs
2278
- });
2313
+ const current = head.stdout.trim();
2314
+ if (head.exitCode !== 0 || !current || current === "HEAD" || current !== branch) {
2315
+ return { updated: false, reason: "not-on-default" };
2279
2316
  }
2280
- try {
2281
- startPoint = await resolveWorktreeStartPoint(
2282
- opts.repoPath,
2283
- opts.sourceRef
2284
- );
2285
- } catch (err) {
2286
- if (!startPoint) throw err;
2317
+ if (await isDirty(repoPath)) {
2318
+ return { updated: false, reason: "dirty" };
2287
2319
  }
2288
- }
2289
- if (!startPoint) {
2290
- throw new Error(
2291
- `Invalid git reference: ${opts.sourceRef} (and fetch did not resolve it)`
2320
+ const remote = `origin/${branch}`;
2321
+ const remoteOk = await git(["rev-parse", "--verify", remote], repoPath, {
2322
+ reject: false
2323
+ });
2324
+ if (remoteOk.exitCode !== 0) {
2325
+ return { updated: false, reason: "no-origin-tip" };
2326
+ }
2327
+ const ancestor = await git(
2328
+ ["merge-base", "--is-ancestor", "HEAD", remote],
2329
+ repoPath,
2330
+ { reject: false }
2331
+ );
2332
+ if (ancestor.exitCode !== 0) {
2333
+ return { updated: false, reason: "diverged" };
2334
+ }
2335
+ const behind = await git(
2336
+ ["rev-list", "--count", `HEAD..${remote}`],
2337
+ repoPath,
2338
+ { reject: false }
2292
2339
  );
2340
+ const n = Number(behind.stdout.trim());
2341
+ if (behind.exitCode !== 0 || !Number.isFinite(n) || n <= 0) {
2342
+ return { updated: false, reason: "already-current" };
2343
+ }
2344
+ const ff = await git(["merge", "--ff-only", remote], repoPath, {
2345
+ reject: false
2346
+ });
2347
+ if (ff.exitCode !== 0) {
2348
+ return { updated: false, reason: "ff-failed" };
2349
+ }
2350
+ return { updated: true, reason: "updated" };
2351
+ } catch {
2352
+ return { updated: false, reason: "ff-failed" };
2353
+ }
2354
+ }
2355
+ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
2356
+ if (!isLocalPrFetchBranch(sourceRef)) {
2357
+ await fetchOriginForWorktree(repoPath, sourceRef);
2358
+ }
2359
+ const def = await resolveDefaultBranch(repoPath, { network: false });
2360
+ if (originFetchBranch(sourceRef) !== def) {
2361
+ await fetchOriginForWorktree(repoPath, def);
2362
+ }
2363
+ await fastForwardMainCheckoutIfSafe(repoPath, { branch: def });
2364
+ }
2365
+ async function createThreadWorktree(opts) {
2366
+ let branchName = `thread/${opts.slug}`;
2367
+ const worktreePath = join2(worktreesRoot(opts.repoPath), opts.slug);
2368
+ if (existsSync2(worktreePath)) {
2369
+ throw new Error(`Worktree already exists at ${worktreePath}`);
2293
2370
  }
2371
+ await ensureGhPreferOrigin(opts.repoPath);
2372
+ await refreshOriginAndMaybeFastForwardMain(opts.repoPath, opts.sourceRef);
2373
+ const startPoint = await resolveWorktreeStartPoint(
2374
+ opts.repoPath,
2375
+ opts.sourceRef
2376
+ );
2294
2377
  const added = await withRepoGitLock(opts.repoPath, async () => {
2295
2378
  const add = await git(
2296
2379
  ["worktree", "add", "-b", branchName, worktreePath, startPoint],
@@ -2327,10 +2410,7 @@ async function createExistingBranchWorktree(opts) {
2327
2410
  throw new Error(`Worktree already exists at ${worktreePath}`);
2328
2411
  }
2329
2412
  await ensureGhPreferOrigin(opts.repoPath);
2330
- await git(["fetch", "origin", "--prune"], opts.repoPath, { reject: false });
2331
- if (!branchName.startsWith("origin/") && !branchName.startsWith("refs/")) {
2332
- await git(["fetch", "origin", branchName], opts.repoPath, { reject: false });
2333
- }
2413
+ await refreshOriginAndMaybeFastForwardMain(opts.repoPath, branchName);
2334
2414
  const existing = await listWorktrees(opts.repoPath);
2335
2415
  const already = existing.find((w) => w.branch === branchName);
2336
2416
  if (already?.path) {
@@ -2792,6 +2872,9 @@ export {
2792
2872
  getPrDetails,
2793
2873
  fetchPrHead,
2794
2874
  resolveWorktreeStartPoint,
2875
+ originFetchBranch,
2876
+ fetchOriginForWorktree,
2877
+ fastForwardMainCheckoutIfSafe,
2795
2878
  createThreadWorktree,
2796
2879
  createExistingBranchWorktree,
2797
2880
  removeWorktree,
@@ -18,13 +18,13 @@ import {
18
18
  stripBrightsyNdjsonNoise,
19
19
  sumUsageList,
20
20
  toolDescription
21
- } from "./chunk-UJWGZM4K.js";
21
+ } from "./chunk-WWH4NNBH.js";
22
22
  import {
23
23
  addWorkspace,
24
24
  ensureWorkspace,
25
25
  removeWorkspace,
26
26
  syncWorkspacesFromThreads
27
- } from "./chunk-3UD2LW4P.js";
27
+ } from "./chunk-JHZ6HGRI.js";
28
28
  import {
29
29
  assertOrchestratorCapableAgent,
30
30
  attachmentsFromWorktreePaths,
@@ -41,14 +41,14 @@ import {
41
41
  persistPendingFileAttachments,
42
42
  stageAbsolutePathsAsAttachments,
43
43
  stageBuffersAsAttachments
44
- } from "./chunk-G3KLNP2B.js";
44
+ } from "./chunk-IHSR7EVK.js";
45
45
  import {
46
46
  SLACK_REPLY_FORMATTING,
47
47
  coordinatorSystemPrompt,
48
48
  coordinatorTurnReminder,
49
49
  enrichWorkspacesWithGithub,
50
50
  ensureGlobalCoordinatorCwd
51
- } from "./chunk-DN7UA3UT.js";
51
+ } from "./chunk-SXPTL222.js";
52
52
  import {
53
53
  httpFetch
54
54
  } from "./chunk-ELBYOGVA.js";
@@ -90,6 +90,8 @@ import {
90
90
  currentBranch,
91
91
  detectGhStack,
92
92
  enqueueByKey,
93
+ fastForwardMainCheckoutIfSafe,
94
+ fetchOriginForWorktree,
93
95
  fetchPrHead,
94
96
  formatGhLandError,
95
97
  formatGitAuthModeDirective,
@@ -123,7 +125,7 @@ import {
123
125
  withRepoGitLock,
124
126
  worktreeDisplayLabelForGroup,
125
127
  worktreeNameFromPath
126
- } from "./chunk-JSYIBLBK.js";
128
+ } from "./chunk-YP3CSOZ6.js";
127
129
  import {
128
130
  ATTACHMENTS_DIR,
129
131
  LEGACY_ATTACHMENTS_DIR
@@ -454,7 +456,7 @@ async function continueSourceThread(threadId, prompt) {
454
456
  await continueOnReply(threadId, prompt);
455
457
  return;
456
458
  }
457
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-XPGJV7JK.js");
459
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-KWV2PPML.js");
458
460
  await getOrchestrator2().send(threadId, prompt);
459
461
  } catch {
460
462
  }
@@ -734,9 +736,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
734
736
  `Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
735
737
  );
736
738
  }
737
- const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-6WR7OGMI.js");
739
+ const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-EZVQPMWT.js");
738
740
  if (isGlobalThread2(thread)) {
739
- const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-J2WBXGLP.js");
741
+ const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-6EPVHVGJ.js");
740
742
  ensureGlobalCoordinatorCwd2(
741
743
  isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
742
744
  );
@@ -2963,6 +2965,8 @@ async function createThread(input, _onSetupLine) {
2963
2965
  `Cowboy mode uses ${defaultBranch} in the project folder. Switch that checkout to ${defaultBranch} first (currently ${head}).`
2964
2966
  );
2965
2967
  }
2968
+ await fetchOriginForWorktree(repoPath, defaultBranch);
2969
+ await fastForwardMainCheckoutIfSafe(repoPath, { branch: defaultBranch });
2966
2970
  const explicitTitle2 = input.title?.trim();
2967
2971
  const thread2 = createEmptyThread({
2968
2972
  title: explicitTitle2 || `Cowboy \xB7 ${head}`,
@@ -3069,7 +3073,7 @@ async function createThread(input, _onSetupLine) {
3069
3073
  return readThread(thread.id) ?? thread;
3070
3074
  }
3071
3075
  async function listLinearIssues(agent, repoPath) {
3072
- const { getAdapter: getAdapter2 } = await import("./agents-VFBNZHI4.js");
3076
+ const { getAdapter: getAdapter2 } = await import("./agents-YVETHB2R.js");
3073
3077
  await requireAgent(agent, { requireLinear: true });
3074
3078
  const adapter = getAdapter2(agent);
3075
3079
  if (!adapter.listLinearIssues) {
@@ -3476,7 +3480,7 @@ async function adoptThread(input) {
3476
3480
  messages: input.messages ?? []
3477
3481
  });
3478
3482
  writeThread(thread);
3479
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-WALT3MJB.js");
3483
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-ZJATBC4A.js");
3480
3484
  await ensureWorkspace2(repoPath);
3481
3485
  return thread;
3482
3486
  }
@@ -5924,7 +5928,7 @@ function formatScheduledPrompt(name, prompt) {
5924
5928
  ${prompt}`;
5925
5929
  }
5926
5930
  async function defaultDeps() {
5927
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-XPGJV7JK.js");
5931
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-KWV2PPML.js");
5928
5932
  const orch = getOrchestrator2();
5929
5933
  return {
5930
5934
  findThread: (id) => findThreadByRef(id),
@@ -7860,7 +7864,7 @@ var Orchestrator = class {
7860
7864
  this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
7861
7865
  if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
7862
7866
  try {
7863
- const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-WALT3MJB.js");
7867
+ const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-ZJATBC4A.js");
7864
7868
  await ensureWorkspace2(thread.repoPath);
7865
7869
  } catch {
7866
7870
  }
@@ -7914,7 +7918,7 @@ var Orchestrator = class {
7914
7918
  `Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
7915
7919
  );
7916
7920
  }
7917
- const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-3NLPMA7K.js");
7921
+ const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-RZRJNHYL.js");
7918
7922
  const slug = thread.worktreePath.split("/").pop();
7919
7923
  const dest = thread.worktreePath;
7920
7924
  await withRepoGitLock(thread.repoPath, async () => {
@@ -8022,7 +8026,7 @@ async function startOrchestration(opts) {
8022
8026
  sourceRef: "default",
8023
8027
  ...createOpts
8024
8028
  }).catch(async () => {
8025
- const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-3NLPMA7K.js");
8029
+ const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-RZRJNHYL.js");
8026
8030
  const repo = await resolveRepoRoot2(repoPath);
8027
8031
  const def = await resolveDefaultBranch2(repo);
8028
8032
  return orch.createThread({
@@ -9,8 +9,8 @@ import {
9
9
  enrichWorkspacesWithGithub,
10
10
  ensureGlobalCoordinatorCwd,
11
11
  formatWorkspaceInventory
12
- } from "./chunk-2C5RE7K4.js";
13
- import "./chunk-QS5JJ2IM.js";
12
+ } from "./chunk-67K3FRKR.js";
13
+ import "./chunk-JTPDWTWJ.js";
14
14
  import "./chunk-B3SJXYIJ.js";
15
15
  import "./chunk-EUXOHTUK.js";
16
16
  import "./chunk-KPIYENTF.js";
@@ -7,8 +7,8 @@ import {
7
7
  enrichWorkspacesWithGithub,
8
8
  ensureGlobalCoordinatorCwd,
9
9
  formatWorkspaceInventory
10
- } from "./chunk-DN7UA3UT.js";
11
- import "./chunk-JSYIBLBK.js";
10
+ } from "./chunk-SXPTL222.js";
11
+ import "./chunk-YP3CSOZ6.js";
12
12
  import "./chunk-FKOIHGKV.js";
13
13
  import "./chunk-I77RYPOH.js";
14
14
  import "./chunk-4TR3HZFT.js";
@@ -15,9 +15,9 @@ import {
15
15
  orchestratorSessionPoisonedByBuiltins,
16
16
  slackCoordinatorSourceRef,
17
17
  takenTeamSlugsForOrchestration
18
- } from "./chunk-G3KLNP2B.js";
19
- import "./chunk-DN7UA3UT.js";
20
- import "./chunk-JSYIBLBK.js";
18
+ } from "./chunk-IHSR7EVK.js";
19
+ import "./chunk-SXPTL222.js";
20
+ import "./chunk-YP3CSOZ6.js";
21
21
  import "./chunk-FKOIHGKV.js";
22
22
  import "./chunk-I77RYPOH.js";
23
23
  import "./chunk-4TR3HZFT.js";
@@ -17,9 +17,9 @@ import {
17
17
  orchestratorSessionPoisonedByBuiltins,
18
18
  slackCoordinatorSourceRef,
19
19
  takenTeamSlugsForOrchestration
20
- } from "./chunk-XUYIJY6D.js";
21
- import "./chunk-2C5RE7K4.js";
22
- import "./chunk-QS5JJ2IM.js";
20
+ } from "./chunk-KNE3FZ46.js";
21
+ import "./chunk-67K3FRKR.js";
22
+ import "./chunk-JTPDWTWJ.js";
23
23
  import "./chunk-B3SJXYIJ.js";
24
24
  import "./chunk-EUXOHTUK.js";
25
25
  import "./chunk-KPIYENTF.js";
package/dist/index.cjs CHANGED
@@ -4952,6 +4952,8 @@ __export(worktree_exports, {
4952
4952
  currentBranch: () => currentBranch,
4953
4953
  detectLocalMergeConflicts: () => detectLocalMergeConflicts,
4954
4954
  ensureGhPreferOrigin: () => ensureGhPreferOrigin,
4955
+ fastForwardMainCheckoutIfSafe: () => fastForwardMainCheckoutIfSafe,
4956
+ fetchOriginForWorktree: () => fetchOriginForWorktree,
4955
4957
  fetchPrHead: () => fetchPrHead,
4956
4958
  getPr: () => getPr,
4957
4959
  getPrChecks: () => getPrChecks,
@@ -4972,6 +4974,7 @@ __export(worktree_exports, {
4972
4974
  markPrReady: () => markPrReady,
4973
4975
  mergePr: () => mergePr,
4974
4976
  normalizeWorktreePath: () => normalizeWorktreePath,
4977
+ originFetchBranch: () => originFetchBranch,
4975
4978
  originGhRepoEnv: () => originGhRepoEnv,
4976
4979
  parseGithubSlugFromRemoteUrl: () => parseGithubSlugFromRemoteUrl,
4977
4980
  pushBranch: () => pushBranch,
@@ -5750,45 +5753,128 @@ async function resolveWorktreeStartPoint(repoPath, sourceRef) {
5750
5753
  function isLocalPrFetchBranch(ref) {
5751
5754
  return /^sideboard-pr-\d+$/.test(ref.trim());
5752
5755
  }
5753
- async function createThreadWorktree(opts) {
5754
- let branchName = `thread/${opts.slug}`;
5755
- const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
5756
- if ((0, import_node_fs16.existsSync)(worktreePath)) {
5757
- throw new Error(`Worktree already exists at ${worktreePath}`);
5756
+ function originFetchBranch(sourceRef) {
5757
+ const ref = sourceRef.trim();
5758
+ if (!ref || isLocalPrFetchBranch(ref)) return null;
5759
+ if (ref.startsWith("refs/remotes/origin/")) {
5760
+ return ref.slice("refs/remotes/origin/".length) || null;
5758
5761
  }
5759
- await ensureGhPreferOrigin(opts.repoPath);
5760
- let startPoint = null;
5762
+ if (ref.startsWith("refs/heads/")) {
5763
+ return ref.slice("refs/heads/".length) || null;
5764
+ }
5765
+ if (ref.startsWith("refs/")) return null;
5766
+ if (ref.startsWith("origin/")) return ref.slice("origin/".length) || null;
5767
+ return ref;
5768
+ }
5769
+ async function fetchOriginWithAuth(repoPath, args, timeoutMs) {
5770
+ const first = await git(args, repoPath, { reject: false, timeoutMs });
5771
+ if (first.exitCode === 0) return true;
5772
+ let mode;
5761
5773
  try {
5762
- startPoint = await resolveWorktreeStartPoint(opts.repoPath, opts.sourceRef);
5774
+ mode = getGithubGitAuthMode();
5763
5775
  } catch {
5764
- startPoint = null;
5776
+ return false;
5765
5777
  }
5766
- if (!isLocalPrFetchBranch(opts.sourceRef)) {
5767
- const fetchTimeoutMs = startPoint ? 12e3 : 45e3;
5768
- await git(["fetch", "origin", "--prune"], opts.repoPath, {
5769
- reject: false,
5770
- timeoutMs: fetchTimeoutMs
5778
+ if (mode === "ssh") return false;
5779
+ const token = await resolveGithubAgentToken(mode, repoPath);
5780
+ if (!token) return false;
5781
+ const tryHttps = async (header) => git(args, repoPath, {
5782
+ reject: false,
5783
+ timeoutMs,
5784
+ env: { GIT_TERMINAL_PROMPT: "0" },
5785
+ config: {
5786
+ "url.https://github.com/.insteadOf": "git@github.com:",
5787
+ "http.extraHeader": header
5788
+ }
5789
+ });
5790
+ const bearer = await tryHttps(`AUTHORIZATION: bearer ${token}`);
5791
+ if (bearer.exitCode === 0) return true;
5792
+ const basic = Buffer.from(`x-access-token:${token}`, "utf8").toString("base64");
5793
+ const basicFetch = await tryHttps(`Authorization: Basic ${basic}`);
5794
+ return basicFetch.exitCode === 0;
5795
+ }
5796
+ async function fetchOriginForWorktree(repoPath, sourceRef, opts) {
5797
+ const timeoutMs = opts?.timeoutMs ?? 2e4;
5798
+ const branch = originFetchBranch(sourceRef);
5799
+ if (!branch) return false;
5800
+ const tipOk = await fetchOriginWithAuth(
5801
+ repoPath,
5802
+ ["fetch", "origin", branch],
5803
+ timeoutMs
5804
+ );
5805
+ await fetchOriginWithAuth(repoPath, ["fetch", "origin", "--prune"], timeoutMs);
5806
+ return tipOk;
5807
+ }
5808
+ async function fastForwardMainCheckoutIfSafe(repoPath, opts) {
5809
+ try {
5810
+ const branch = opts?.branch?.trim() || await resolveDefaultBranch(repoPath, { network: false });
5811
+ const head = await git(["rev-parse", "--abbrev-ref", "HEAD"], repoPath, {
5812
+ reject: false
5771
5813
  });
5772
- if (!opts.sourceRef.startsWith("origin/") && !opts.sourceRef.startsWith("refs/")) {
5773
- await git(["fetch", "origin", opts.sourceRef], opts.repoPath, {
5774
- reject: false,
5775
- timeoutMs: fetchTimeoutMs
5776
- });
5814
+ const current = head.stdout.trim();
5815
+ if (head.exitCode !== 0 || !current || current === "HEAD" || current !== branch) {
5816
+ return { updated: false, reason: "not-on-default" };
5777
5817
  }
5778
- try {
5779
- startPoint = await resolveWorktreeStartPoint(
5780
- opts.repoPath,
5781
- opts.sourceRef
5782
- );
5783
- } catch (err) {
5784
- if (!startPoint) throw err;
5818
+ if (await isDirty(repoPath)) {
5819
+ return { updated: false, reason: "dirty" };
5785
5820
  }
5786
- }
5787
- if (!startPoint) {
5788
- throw new Error(
5789
- `Invalid git reference: ${opts.sourceRef} (and fetch did not resolve it)`
5821
+ const remote = `origin/${branch}`;
5822
+ const remoteOk = await git(["rev-parse", "--verify", remote], repoPath, {
5823
+ reject: false
5824
+ });
5825
+ if (remoteOk.exitCode !== 0) {
5826
+ return { updated: false, reason: "no-origin-tip" };
5827
+ }
5828
+ const ancestor = await git(
5829
+ ["merge-base", "--is-ancestor", "HEAD", remote],
5830
+ repoPath,
5831
+ { reject: false }
5790
5832
  );
5833
+ if (ancestor.exitCode !== 0) {
5834
+ return { updated: false, reason: "diverged" };
5835
+ }
5836
+ const behind = await git(
5837
+ ["rev-list", "--count", `HEAD..${remote}`],
5838
+ repoPath,
5839
+ { reject: false }
5840
+ );
5841
+ const n = Number(behind.stdout.trim());
5842
+ if (behind.exitCode !== 0 || !Number.isFinite(n) || n <= 0) {
5843
+ return { updated: false, reason: "already-current" };
5844
+ }
5845
+ const ff = await git(["merge", "--ff-only", remote], repoPath, {
5846
+ reject: false
5847
+ });
5848
+ if (ff.exitCode !== 0) {
5849
+ return { updated: false, reason: "ff-failed" };
5850
+ }
5851
+ return { updated: true, reason: "updated" };
5852
+ } catch {
5853
+ return { updated: false, reason: "ff-failed" };
5854
+ }
5855
+ }
5856
+ async function refreshOriginAndMaybeFastForwardMain(repoPath, sourceRef) {
5857
+ if (!isLocalPrFetchBranch(sourceRef)) {
5858
+ await fetchOriginForWorktree(repoPath, sourceRef);
5791
5859
  }
5860
+ const def = await resolveDefaultBranch(repoPath, { network: false });
5861
+ if (originFetchBranch(sourceRef) !== def) {
5862
+ await fetchOriginForWorktree(repoPath, def);
5863
+ }
5864
+ await fastForwardMainCheckoutIfSafe(repoPath, { branch: def });
5865
+ }
5866
+ async function createThreadWorktree(opts) {
5867
+ let branchName = `thread/${opts.slug}`;
5868
+ const worktreePath = (0, import_node_path18.join)(worktreesRoot(opts.repoPath), opts.slug);
5869
+ if ((0, import_node_fs16.existsSync)(worktreePath)) {
5870
+ throw new Error(`Worktree already exists at ${worktreePath}`);
5871
+ }
5872
+ await ensureGhPreferOrigin(opts.repoPath);
5873
+ await refreshOriginAndMaybeFastForwardMain(opts.repoPath, opts.sourceRef);
5874
+ const startPoint = await resolveWorktreeStartPoint(
5875
+ opts.repoPath,
5876
+ opts.sourceRef
5877
+ );
5792
5878
  const added = await withRepoGitLock(opts.repoPath, async () => {
5793
5879
  const add = await git(
5794
5880
  ["worktree", "add", "-b", branchName, worktreePath, startPoint],
@@ -5825,10 +5911,7 @@ async function createExistingBranchWorktree(opts) {
5825
5911
  throw new Error(`Worktree already exists at ${worktreePath}`);
5826
5912
  }
5827
5913
  await ensureGhPreferOrigin(opts.repoPath);
5828
- await git(["fetch", "origin", "--prune"], opts.repoPath, { reject: false });
5829
- if (!branchName.startsWith("origin/") && !branchName.startsWith("refs/")) {
5830
- await git(["fetch", "origin", branchName], opts.repoPath, { reject: false });
5831
- }
5914
+ await refreshOriginAndMaybeFastForwardMain(opts.repoPath, branchName);
5832
5915
  const existing = await listWorktrees(opts.repoPath);
5833
5916
  const already = existing.find((w) => w.branch === branchName);
5834
5917
  if (already?.path) {
@@ -14964,6 +15047,8 @@ async function createThread(input, _onSetupLine) {
14964
15047
  `Cowboy mode uses ${defaultBranch} in the project folder. Switch that checkout to ${defaultBranch} first (currently ${head}).`
14965
15048
  );
14966
15049
  }
15050
+ await fetchOriginForWorktree(repoPath, defaultBranch);
15051
+ await fastForwardMainCheckoutIfSafe(repoPath, { branch: defaultBranch });
14967
15052
  const explicitTitle2 = input.title?.trim();
14968
15053
  const thread2 = createEmptyThread({
14969
15054
  title: explicitTitle2 || `Cowboy \xB7 ${head}`,
@@ -20481,6 +20566,8 @@ __export(index_exports, {
20481
20566
  extractPendingPlanQuestions: () => extractPendingPlanQuestions,
20482
20567
  extractPresentedPlan: () => extractPresentedPlan,
20483
20568
  extractiveSummary: () => extractiveSummary,
20569
+ fastForwardMainCheckoutIfSafe: () => fastForwardMainCheckoutIfSafe,
20570
+ fetchOriginForWorktree: () => fetchOriginForWorktree,
20484
20571
  fetchPrHead: () => fetchPrHead,
20485
20572
  finalizeParts: () => finalizeParts,
20486
20573
  findConventionSetup: () => findConventionSetup,
@@ -20723,6 +20810,7 @@ __export(index_exports, {
20723
20810
  orchestrationQuotaOnLimit: () => orchestrationQuotaOnLimit,
20724
20811
  orchestrationTitleNeedsSoccerNickname: () => orchestrationTitleNeedsSoccerNickname,
20725
20812
  orchestratorSessionPoisonedByBuiltins: () => orchestratorSessionPoisonedByBuiltins,
20813
+ originFetchBranch: () => originFetchBranch,
20726
20814
  originGhRepoEnv: () => originGhRepoEnv,
20727
20815
  packagedDetachedJobPath: () => packagedDetachedJobPath,
20728
20816
  parseCursorRunnerLine: () => parseCursorRunnerLine,
@@ -27069,6 +27157,8 @@ init_outbound_watch();
27069
27157
  extractPendingPlanQuestions,
27070
27158
  extractPresentedPlan,
27071
27159
  extractiveSummary,
27160
+ fastForwardMainCheckoutIfSafe,
27161
+ fetchOriginForWorktree,
27072
27162
  fetchPrHead,
27073
27163
  finalizeParts,
27074
27164
  findConventionSetup,
@@ -27311,6 +27401,7 @@ init_outbound_watch();
27311
27401
  orchestrationQuotaOnLimit,
27312
27402
  orchestrationTitleNeedsSoccerNickname,
27313
27403
  orchestratorSessionPoisonedByBuiltins,
27404
+ originFetchBranch,
27314
27405
  originGhRepoEnv,
27315
27406
  packagedDetachedJobPath,
27316
27407
  parseCursorRunnerLine,