@sideboard-ai/core 0.1.15 → 0.1.19
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.
- package/dist/{agents-RO3AJ76Q.js → agents-2XMZO3CY.js} +1 -1
- package/dist/{chunk-3OJG4LP4.js → chunk-5263JXQY.js} +2 -2
- package/dist/{chunk-MEI4AXV4.js → chunk-JQJZTL2Q.js} +1 -1
- package/dist/{chunk-MGSJQMJA.js → chunk-LIUV5ONW.js} +7 -3
- package/dist/{chunk-L44AX7IG.js → chunk-LXHSRNJJ.js} +116 -28
- package/dist/{chunk-TNIAXABV.js → chunk-SNHWAARD.js} +6 -5
- package/dist/{chunk-MAWKQA2Y.js → chunk-WWBC56EL.js} +37 -17
- package/dist/{coordinator-prompt-G6T7ORT3.js → coordinator-prompt-QPTX6YCW.js} +2 -2
- package/dist/{global-workspace-H642B5OI.js → global-workspace-IV6LIDTO.js} +3 -3
- package/dist/index.cjs +160 -39
- package/dist/index.d.cts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +14 -6
- package/dist/mcp/run-stdio.cjs +2680 -2567
- package/dist/mcp/run-stdio.js +6 -6
- package/dist/{workspaces-4EREGLB7.js → workspaces-JBWIRU55.js} +4 -4
- package/dist/{worktree-ZDHZMLSJ.js → worktree-TYI2SANE.js} +9 -1
- package/package.json +1 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureGlobalCoordinatorCwd
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SNHWAARD.js";
|
|
4
4
|
import {
|
|
5
5
|
allocateTeamName,
|
|
6
6
|
takenSlugsFromThread,
|
|
7
7
|
teamSlugFromName
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LXHSRNJJ.js";
|
|
9
9
|
import {
|
|
10
10
|
createEmptyThread,
|
|
11
11
|
listThreads,
|
|
@@ -719,7 +719,7 @@ var claudeAdapter = {
|
|
|
719
719
|
);
|
|
720
720
|
}
|
|
721
721
|
const mode = permissionMode(thread);
|
|
722
|
-
const { isOrchestratorThread } = await import("./global-workspace-
|
|
722
|
+
const { isOrchestratorThread } = await import("./global-workspace-IV6LIDTO.js");
|
|
723
723
|
const isOrchestrator = isOrchestratorThread(thread);
|
|
724
724
|
const injectedServers = await buildInjectedMcpServers({
|
|
725
725
|
includeSideboard: isOrchestrator,
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isGlobalRepoPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-5263JXQY.js";
|
|
4
4
|
import {
|
|
5
|
+
ensureGhPreferOrigin,
|
|
5
6
|
resolveRepoRoot
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-LXHSRNJJ.js";
|
|
7
8
|
import {
|
|
8
9
|
appDataDir
|
|
9
10
|
} from "./chunk-M37RITA6.js";
|
|
@@ -57,7 +58,9 @@ function forgetRemoved(repoPath) {
|
|
|
57
58
|
}
|
|
58
59
|
function listWorkspaces() {
|
|
59
60
|
const all = readAll();
|
|
60
|
-
const valid = all.filter(
|
|
61
|
+
const valid = all.filter(
|
|
62
|
+
(w) => Boolean(w.path) && w.path !== "/" && w.path !== "." && !isGlobalRepoPath(w.path)
|
|
63
|
+
);
|
|
61
64
|
if (valid.length !== all.length) writeAll(valid);
|
|
62
65
|
return valid.sort((a, b) => a.name.localeCompare(b.name));
|
|
63
66
|
}
|
|
@@ -66,6 +69,7 @@ async function addWorkspace(repoPath) {
|
|
|
66
69
|
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
67
70
|
if (!existsSync(root)) throw new Error(`Repo not found: ${root}`);
|
|
68
71
|
forgetRemoved(root);
|
|
72
|
+
await ensureGhPreferOrigin(root);
|
|
69
73
|
const current = readAll();
|
|
70
74
|
const existing = current.find((w) => w.path === root);
|
|
71
75
|
if (existing) return existing;
|
|
@@ -492,6 +492,16 @@ function formatGhLandError(raw, opts) {
|
|
|
492
492
|
return trimmed;
|
|
493
493
|
}
|
|
494
494
|
const detail = extractGhErrorDetail(raw);
|
|
495
|
+
if (/Head ref must be a branch|No commits between|Head sha can't be blank/i.test(
|
|
496
|
+
raw
|
|
497
|
+
) || /Head ref must be a branch|No commits between|Head sha can't be blank/i.test(
|
|
498
|
+
detail
|
|
499
|
+
)) {
|
|
500
|
+
const target = opts?.targetedRepo ? ` Targeted ${opts.targetedRepo}` : "";
|
|
501
|
+
const head = opts?.headRef ? ` with head ${opts.headRef}` : "";
|
|
502
|
+
const hint = opts?.targetedRepo ? ` Branch was pushed to origin \u2014 confirm it exists on GitHub and differs from the base branch.${target}${head}.` : " Often `gh` targeted upstream instead of origin. Branch was pushed \u2014 retry in the latest Sideboard, or run: gh pr create -R <owner/name> --base main --head <branch>.";
|
|
503
|
+
return `Could not create the pull request.${hint}`;
|
|
504
|
+
}
|
|
495
505
|
if (isGhRateLimitError(raw) || isGhRateLimitError(detail)) {
|
|
496
506
|
const when = opts?.resetAt ? ` Try again ${formatRateLimitResetHint(opts.resetAt, opts.nowMs)}.` : " Wait a few minutes and try again.";
|
|
497
507
|
const pushNote = opts?.pushed === false ? "" : " Your branch was already pushed.";
|
|
@@ -606,12 +616,19 @@ async function lookupGithubGraphqlReset(cwd) {
|
|
|
606
616
|
return void 0;
|
|
607
617
|
}
|
|
608
618
|
}
|
|
609
|
-
async function formatPrCreateFailure(raw, cwd) {
|
|
619
|
+
async function formatPrCreateFailure(raw, cwd, ctx) {
|
|
610
620
|
if (!isGhRateLimitError(raw)) {
|
|
611
|
-
return formatGhLandError(raw
|
|
621
|
+
return formatGhLandError(raw, {
|
|
622
|
+
targetedRepo: ctx?.slug,
|
|
623
|
+
headRef: ctx?.head
|
|
624
|
+
});
|
|
612
625
|
}
|
|
613
626
|
const resetAt = await lookupGithubGraphqlReset(cwd);
|
|
614
|
-
return formatGhLandError(raw, {
|
|
627
|
+
return formatGhLandError(raw, {
|
|
628
|
+
resetAt,
|
|
629
|
+
targetedRepo: ctx?.slug,
|
|
630
|
+
headRef: ctx?.head
|
|
631
|
+
});
|
|
615
632
|
}
|
|
616
633
|
function slugify(input) {
|
|
617
634
|
return input.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 48);
|
|
@@ -621,10 +638,13 @@ async function resolveRepoRoot(cwd) {
|
|
|
621
638
|
return stdout.trim();
|
|
622
639
|
}
|
|
623
640
|
function parseGithubSlugFromRemoteUrl(url) {
|
|
624
|
-
const trimmed = url.trim();
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
return `${
|
|
641
|
+
const trimmed = url.trim().replace(/\.git$/i, "");
|
|
642
|
+
if (!trimmed) return null;
|
|
643
|
+
const github = trimmed.match(/github\.com[:/]([^/]+)\/([^/]+)$/i);
|
|
644
|
+
if (github?.[1] && github[2]) return `${github[1]}/${github[2]}`;
|
|
645
|
+
const sshAlias = trimmed.match(/^git@[^:]+:([^/]+)\/([^/]+)$/i);
|
|
646
|
+
if (sshAlias?.[1] && sshAlias[2]) return `${sshAlias[1]}/${sshAlias[2]}`;
|
|
647
|
+
return null;
|
|
628
648
|
}
|
|
629
649
|
async function slugFromGitRemote(repoPath, remote) {
|
|
630
650
|
const result = await git(["remote", "get-url", remote], repoPath, {
|
|
@@ -636,13 +656,16 @@ async function slugFromGitRemote(repoPath, remote) {
|
|
|
636
656
|
async function resolveGithubRepoSlug(repoPath) {
|
|
637
657
|
const fromOrigin = await slugFromGitRemote(repoPath, "origin");
|
|
638
658
|
if (fromOrigin) return fromOrigin;
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
659
|
+
const hasAlt = Boolean(await slugFromGitRemote(repoPath, "upstream")) || Boolean(await slugFromGitRemote(repoPath, "github"));
|
|
660
|
+
if (!hasAlt) {
|
|
661
|
+
const viaGh = await gh(
|
|
662
|
+
["repo", "view", "--json", "nameWithOwner", "--jq", ".nameWithOwner"],
|
|
663
|
+
repoPath,
|
|
664
|
+
{ reject: false }
|
|
665
|
+
);
|
|
666
|
+
if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
|
|
667
|
+
return viaGh.stdout.trim();
|
|
668
|
+
}
|
|
646
669
|
}
|
|
647
670
|
for (const remote of ["upstream", "github"]) {
|
|
648
671
|
const slug = await slugFromGitRemote(repoPath, remote);
|
|
@@ -650,15 +673,35 @@ async function resolveGithubRepoSlug(repoPath) {
|
|
|
650
673
|
}
|
|
651
674
|
return null;
|
|
652
675
|
}
|
|
676
|
+
function ghRepoSelectArgs(slug) {
|
|
677
|
+
return ["-R", slug];
|
|
678
|
+
}
|
|
679
|
+
function ghHeadRef(slug, branch) {
|
|
680
|
+
const owner = slug.split("/")[0];
|
|
681
|
+
const head = branch.trim().replace(/^refs\/heads\//, "");
|
|
682
|
+
if (!owner || !head) return head || branch;
|
|
683
|
+
if (head.includes(":")) return head;
|
|
684
|
+
return `${owner}:${head}`;
|
|
685
|
+
}
|
|
686
|
+
async function ensureGhPreferOrigin(cwd) {
|
|
687
|
+
const originSlug = await slugFromGitRemote(cwd, "origin");
|
|
688
|
+
if (!originSlug) return;
|
|
689
|
+
const hasAlt = Boolean(await slugFromGitRemote(cwd, "upstream")) || Boolean(await slugFromGitRemote(cwd, "github"));
|
|
690
|
+
if (!hasAlt) return;
|
|
691
|
+
const view = await gh(["repo", "set-default", "--view"], cwd, {
|
|
692
|
+
reject: false
|
|
693
|
+
});
|
|
694
|
+
const current = `${view.stdout}
|
|
695
|
+
${view.stderr}`;
|
|
696
|
+
if (view.exitCode === 0 && current.includes(originSlug)) return;
|
|
697
|
+
await gh(["repo", "set-default", "origin"], cwd, { reject: false });
|
|
698
|
+
}
|
|
699
|
+
async function originGhRepoEnv(cwd) {
|
|
700
|
+
await ensureGhPreferOrigin(cwd);
|
|
701
|
+
const slug = await resolveGithubRepoSlug(cwd);
|
|
702
|
+
return slug ? { GH_REPO: slug } : {};
|
|
703
|
+
}
|
|
653
704
|
async function resolveDefaultBranch(repoPath) {
|
|
654
|
-
const viaGh = await gh(
|
|
655
|
-
["repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"],
|
|
656
|
-
repoPath,
|
|
657
|
-
{ reject: false }
|
|
658
|
-
);
|
|
659
|
-
if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
|
|
660
|
-
return viaGh.stdout.trim();
|
|
661
|
-
}
|
|
662
705
|
const viaOrigin = await git(
|
|
663
706
|
["symbolic-ref", "refs/remotes/origin/HEAD"],
|
|
664
707
|
repoPath,
|
|
@@ -667,6 +710,31 @@ async function resolveDefaultBranch(repoPath) {
|
|
|
667
710
|
if (viaOrigin.exitCode === 0 && viaOrigin.stdout.trim()) {
|
|
668
711
|
return viaOrigin.stdout.trim().replace(/^refs\/remotes\/origin\//, "");
|
|
669
712
|
}
|
|
713
|
+
const slug = await resolveGithubRepoSlug(repoPath);
|
|
714
|
+
const viaGh = await gh(
|
|
715
|
+
[
|
|
716
|
+
"repo",
|
|
717
|
+
"view",
|
|
718
|
+
...slug ? ["--repo", slug] : [],
|
|
719
|
+
"--json",
|
|
720
|
+
"defaultBranchRef",
|
|
721
|
+
"--jq",
|
|
722
|
+
".defaultBranchRef.name"
|
|
723
|
+
],
|
|
724
|
+
repoPath,
|
|
725
|
+
{ reject: false }
|
|
726
|
+
);
|
|
727
|
+
if (viaGh.exitCode === 0 && viaGh.stdout.trim()) {
|
|
728
|
+
return viaGh.stdout.trim();
|
|
729
|
+
}
|
|
730
|
+
for (const candidate of ["main", "master"]) {
|
|
731
|
+
const check = await git(
|
|
732
|
+
["show-ref", "--verify", "--quiet", `refs/remotes/origin/${candidate}`],
|
|
733
|
+
repoPath,
|
|
734
|
+
{ reject: false }
|
|
735
|
+
);
|
|
736
|
+
if (check.exitCode === 0) return candidate;
|
|
737
|
+
}
|
|
670
738
|
for (const candidate of ["main", "master"]) {
|
|
671
739
|
const check = await git(
|
|
672
740
|
["show-ref", "--verify", "--quiet", `refs/heads/${candidate}`],
|
|
@@ -1072,6 +1140,7 @@ async function createThreadWorktree(opts) {
|
|
|
1072
1140
|
if (existsSync(worktreePath)) {
|
|
1073
1141
|
throw new Error(`Worktree already exists at ${worktreePath}`);
|
|
1074
1142
|
}
|
|
1143
|
+
await ensureGhPreferOrigin(opts.repoPath);
|
|
1075
1144
|
await git(["fetch", "origin", "--prune"], opts.repoPath, { reject: false });
|
|
1076
1145
|
if (!opts.sourceRef.startsWith("origin/") && !opts.sourceRef.startsWith("refs/")) {
|
|
1077
1146
|
await git(["fetch", "origin", opts.sourceRef], opts.repoPath, {
|
|
@@ -1100,6 +1169,7 @@ ${add.stdout}`;
|
|
|
1100
1169
|
);
|
|
1101
1170
|
if (retry.exitCode === 0) {
|
|
1102
1171
|
branchName = alt;
|
|
1172
|
+
await ensureGhPreferOrigin(worktreePath);
|
|
1103
1173
|
return { branchName, worktreePath };
|
|
1104
1174
|
}
|
|
1105
1175
|
}
|
|
@@ -1108,6 +1178,7 @@ ${add.stdout}`;
|
|
|
1108
1178
|
`Failed to create worktree: ${add.stderr.trim() || add.stdout.trim() || `exit ${add.exitCode}`}`
|
|
1109
1179
|
);
|
|
1110
1180
|
}
|
|
1181
|
+
await ensureGhPreferOrigin(worktreePath);
|
|
1111
1182
|
return { branchName, worktreePath };
|
|
1112
1183
|
}
|
|
1113
1184
|
async function removeWorktree(repoPath, worktreePath, opts) {
|
|
@@ -1208,8 +1279,18 @@ async function mergePr(cwd, selector, opts) {
|
|
|
1208
1279
|
return { url, state: "MERGED" };
|
|
1209
1280
|
}
|
|
1210
1281
|
async function createOrUpdatePr(worktreePath, opts) {
|
|
1282
|
+
await ensureGhPreferOrigin(worktreePath);
|
|
1283
|
+
const slug = await resolveGithubRepoSlug(worktreePath);
|
|
1284
|
+
if (!slug) {
|
|
1285
|
+
throw new Error(
|
|
1286
|
+
"Could not resolve the origin GitHub repo (owner/name) for this worktree. Check that `git remote get-url origin` points at github.com."
|
|
1287
|
+
);
|
|
1288
|
+
}
|
|
1289
|
+
const repoArgs = ghRepoSelectArgs(slug);
|
|
1290
|
+
const headRef = ghHeadRef(slug, opts.head);
|
|
1291
|
+
const branchOnly = opts.head.trim().replace(/^refs\/heads\//, "");
|
|
1211
1292
|
const existing = await gh(
|
|
1212
|
-
["pr", "view",
|
|
1293
|
+
[...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
|
|
1213
1294
|
worktreePath,
|
|
1214
1295
|
{ reject: false }
|
|
1215
1296
|
);
|
|
@@ -1217,9 +1298,10 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
1217
1298
|
const url2 = existing.stdout.trim();
|
|
1218
1299
|
await gh(
|
|
1219
1300
|
[
|
|
1301
|
+
...repoArgs,
|
|
1220
1302
|
"pr",
|
|
1221
1303
|
"edit",
|
|
1222
|
-
|
|
1304
|
+
branchOnly,
|
|
1223
1305
|
"--title",
|
|
1224
1306
|
opts.title,
|
|
1225
1307
|
"--body",
|
|
@@ -1232,6 +1314,7 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
1232
1314
|
}
|
|
1233
1315
|
if (opts.web) {
|
|
1234
1316
|
const args2 = [
|
|
1317
|
+
...repoArgs,
|
|
1235
1318
|
"pr",
|
|
1236
1319
|
"create",
|
|
1237
1320
|
"--web",
|
|
@@ -1242,18 +1325,19 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
1242
1325
|
"--base",
|
|
1243
1326
|
opts.base,
|
|
1244
1327
|
"--head",
|
|
1245
|
-
|
|
1328
|
+
headRef
|
|
1246
1329
|
];
|
|
1247
1330
|
if (opts.draft) args2.push("--draft");
|
|
1248
1331
|
await gh(args2, worktreePath, { reject: false });
|
|
1249
1332
|
const again = await gh(
|
|
1250
|
-
["pr", "view",
|
|
1333
|
+
[...repoArgs, "pr", "view", branchOnly, "--json", "url", "--jq", ".url"],
|
|
1251
1334
|
worktreePath,
|
|
1252
1335
|
{ reject: false }
|
|
1253
1336
|
);
|
|
1254
1337
|
return again.stdout.trim() || "";
|
|
1255
1338
|
}
|
|
1256
1339
|
const args = [
|
|
1340
|
+
...repoArgs,
|
|
1257
1341
|
"pr",
|
|
1258
1342
|
"create",
|
|
1259
1343
|
"--title",
|
|
@@ -1263,13 +1347,13 @@ async function createOrUpdatePr(worktreePath, opts) {
|
|
|
1263
1347
|
"--base",
|
|
1264
1348
|
opts.base,
|
|
1265
1349
|
"--head",
|
|
1266
|
-
|
|
1350
|
+
headRef
|
|
1267
1351
|
];
|
|
1268
1352
|
if (opts.draft) args.push("--draft");
|
|
1269
1353
|
const created = await gh(args, worktreePath, { reject: false });
|
|
1270
1354
|
if (created.exitCode !== 0) {
|
|
1271
1355
|
const raw = created.stderr.trim() || created.stdout.trim() || "gh pr create failed";
|
|
1272
|
-
throw new Error(await formatPrCreateFailure(raw, worktreePath));
|
|
1356
|
+
throw new Error(await formatPrCreateFailure(raw, worktreePath, { slug, head: headRef }));
|
|
1273
1357
|
}
|
|
1274
1358
|
const url = created.stdout.trim().split("\n").find((l) => l.startsWith("http")) ?? created.stdout.trim();
|
|
1275
1359
|
return url;
|
|
@@ -1344,6 +1428,10 @@ export {
|
|
|
1344
1428
|
resolveRepoRoot,
|
|
1345
1429
|
parseGithubSlugFromRemoteUrl,
|
|
1346
1430
|
resolveGithubRepoSlug,
|
|
1431
|
+
ghRepoSelectArgs,
|
|
1432
|
+
ghHeadRef,
|
|
1433
|
+
ensureGhPreferOrigin,
|
|
1434
|
+
originGhRepoEnv,
|
|
1347
1435
|
resolveDefaultBranch,
|
|
1348
1436
|
resolveDiffBaseRef,
|
|
1349
1437
|
listBranches,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveGithubRepoSlug
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LXHSRNJJ.js";
|
|
4
4
|
import {
|
|
5
5
|
globalAgentCwd,
|
|
6
6
|
sideboardReposDir
|
|
@@ -31,7 +31,8 @@ function coordinatorGreenfieldPlaybook(reposDir) {
|
|
|
31
31
|
"- Examples:",
|
|
32
32
|
` - Clone: \`git clone <url> ${reposDir}/<name>\``,
|
|
33
33
|
` - New GitHub repo: \`gh repo create <owner>/<name> --private --clone -- ${reposDir}/<name>\` (or mkdir + git init + gh repo create + remote add + push)`,
|
|
34
|
-
"- Then: add_workspace with that absolute path \u2192 create_thread (repoPath + parentThreadId) \u2192 send_to_thread (build) \u2192 wait_for_turn \u2192 send_to_thread (`gh pr create --draft
|
|
34
|
+
"- Then: add_workspace with that absolute path \u2192 create_thread (repoPath + parentThreadId) \u2192 send_to_thread (build) \u2192 wait_for_turn \u2192 send_to_thread (`gh pr create --draft -R <origin-owner/name>`) or create_draft_pr.",
|
|
35
|
+
"- Always target the child worktree's **origin** (`github:` slug from list_workspaces / `git remote get-url origin` in that worktree). Never open PRs against `upstream`.",
|
|
35
36
|
"- Do coding work in the child worktree thread, not by editing files in this home cwd."
|
|
36
37
|
].join("\n");
|
|
37
38
|
}
|
|
@@ -56,8 +57,8 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
56
57
|
"Inspect / PRs:",
|
|
57
58
|
"- get_diff \u2014 compact diff summary",
|
|
58
59
|
"- preview_land \u2014 preview push+PR (does not push)",
|
|
59
|
-
"- Prefer asking the worktree agent via send_to_thread to open a draft PR
|
|
60
|
-
"- create_draft_pr \u2014 fallback: commit (if dirty), push, open/update a DRAFT PR from the orchestrator",
|
|
60
|
+
"- Prefer asking the worktree agent via send_to_thread to open a draft PR with `gh pr create --draft -R <origin-owner/name>` (use the workspace `github:` slug / that worktree's origin \u2014 never upstream) so it owns title/body from the diff.",
|
|
61
|
+
"- create_draft_pr \u2014 fallback: commit (if dirty), push to origin, open/update a DRAFT PR from the orchestrator (always against origin)",
|
|
61
62
|
"Human-only (do not attempt): ready-for-review confirm_land, purge_thread.",
|
|
62
63
|
"Thread links in replies: when mentioning a chat/thread for the user, include a markdown link `[Title](sideboard://thread/<id>)` using the full id (or the link field from create_thread / list_threads). Sideboard renders these as clickable opens.",
|
|
63
64
|
"Bash / Read / etc: allowed for (1) inspecting target worktrees / registered repo paths from MCP, and (2) greenfield setup under ~/sideboard/repos (git clone, gh repo create, git init+remote). Never git init/clone *inside* this synthetic home cwd \u2014 emptiness here is expected, not a bug."
|
|
@@ -123,7 +124,7 @@ function coordinatorSystemPrompt(opts) {
|
|
|
123
124
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
124
125
|
coordinatorGreenfieldPlaybook(reposDir),
|
|
125
126
|
"When creating threads, pass the correct repoPath for the target workspace and parentThreadId for children.",
|
|
126
|
-
"Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 send_to_thread (ask for `gh pr create --draft
|
|
127
|
+
"Typical flow (existing): list_workspaces \u2192 list_branches|list_prs|list_issues \u2192 create_thread \u2192 send_to_thread (implement) \u2192 wait_for_turn \u2192 send_to_thread (ask for `gh pr create --draft -R <origin-owner/name>` using the workspace github slug) \u2192 wait_for_turn. Use create_draft_pr only if the child cannot open the PR. Never target upstream.",
|
|
127
128
|
"Typical flow (new app): Bash under repos dir (clone or gh repo create) \u2192 add_workspace \u2192 create_thread \u2192 send_to_thread \u2192 wait_for_turn \u2192 draft PR.",
|
|
128
129
|
`Goal: ${opts.goal}`,
|
|
129
130
|
`Parent thread id (pass as parentThreadId when creating children): ${opts.parentId}`,
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
ensureWorkspace,
|
|
4
4
|
removeWorkspace,
|
|
5
5
|
syncWorkspacesFromThreads
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-LIUV5ONW.js";
|
|
7
7
|
import {
|
|
8
8
|
GLOBAL_WORKSPACE_ID,
|
|
9
9
|
createGlobalChat,
|
|
@@ -13,19 +13,19 @@ import {
|
|
|
13
13
|
isGlobalThread,
|
|
14
14
|
isOrchestratorThread,
|
|
15
15
|
orchestratorSessionPoisonedByBuiltins
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-5263JXQY.js";
|
|
17
17
|
import {
|
|
18
18
|
coordinatorSystemPrompt,
|
|
19
19
|
coordinatorTurnReminder,
|
|
20
20
|
enrichWorkspacesWithGithub,
|
|
21
21
|
ensureGlobalCoordinatorCwd
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-SNHWAARD.js";
|
|
23
23
|
import {
|
|
24
24
|
PLAN_MODE_INSTRUCTION,
|
|
25
25
|
allAdapters,
|
|
26
26
|
getAdapter,
|
|
27
27
|
parseBrightsyCliLine
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-JQJZTL2Q.js";
|
|
29
29
|
import {
|
|
30
30
|
childEnvWithAppSettings,
|
|
31
31
|
getLinearApiKey,
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
listWorktrees,
|
|
54
54
|
mergePr,
|
|
55
55
|
normalizeWorktreePath,
|
|
56
|
+
originGhRepoEnv,
|
|
56
57
|
pushBranch,
|
|
57
58
|
removeWorktree,
|
|
58
59
|
resolveDefaultBranch,
|
|
@@ -63,7 +64,7 @@ import {
|
|
|
63
64
|
takenSlugsFromThread,
|
|
64
65
|
threadDisplayLabel,
|
|
65
66
|
worktreeNameFromPath
|
|
66
|
-
} from "./chunk-
|
|
67
|
+
} from "./chunk-LXHSRNJJ.js";
|
|
67
68
|
import {
|
|
68
69
|
appendMessage,
|
|
69
70
|
createEmptyThread,
|
|
@@ -431,9 +432,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
431
432
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
432
433
|
);
|
|
433
434
|
}
|
|
434
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
435
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-IV6LIDTO.js");
|
|
435
436
|
if (isGlobalThread2(thread)) {
|
|
436
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
437
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-QPTX6YCW.js");
|
|
437
438
|
ensureGlobalCoordinatorCwd2();
|
|
438
439
|
}
|
|
439
440
|
const adapter = getAdapter(thread.agent);
|
|
@@ -443,9 +444,14 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
443
444
|
`Agent cwd must be the thread worktree (got ${cmd.cwd}, expected ${thread.worktreePath})`
|
|
444
445
|
);
|
|
445
446
|
}
|
|
447
|
+
const env = childEnvWithAppSettings(cmd.env);
|
|
448
|
+
if (!isOrchestratorThread(thread)) {
|
|
449
|
+
const originEnv = await originGhRepoEnv(thread.worktreePath).catch(() => ({}));
|
|
450
|
+
Object.assign(env, originEnv);
|
|
451
|
+
}
|
|
446
452
|
const child = execa(cmd.file, cmd.args, {
|
|
447
453
|
cwd: cmd.cwd,
|
|
448
|
-
env
|
|
454
|
+
env,
|
|
449
455
|
reject: false,
|
|
450
456
|
stdout: "pipe",
|
|
451
457
|
stderr: "pipe",
|
|
@@ -548,7 +554,7 @@ function formatRenameBranchDirective(thread, opts) {
|
|
|
548
554
|
}
|
|
549
555
|
return lines.join("\n");
|
|
550
556
|
}
|
|
551
|
-
function formatWorktreeDirective(thread) {
|
|
557
|
+
function formatWorktreeDirective(thread, opts) {
|
|
552
558
|
const worktree = normPath(thread.worktreePath);
|
|
553
559
|
const repo = normPath(thread.repoPath);
|
|
554
560
|
const dir = worktreeNameFromPath(thread.worktreePath);
|
|
@@ -569,7 +575,13 @@ function formatWorktreeDirective(thread) {
|
|
|
569
575
|
);
|
|
570
576
|
}
|
|
571
577
|
lines.push("");
|
|
572
|
-
lines.push("
|
|
578
|
+
lines.push("Git remotes + pull requests (when the work is ready to share):");
|
|
579
|
+
lines.push(
|
|
580
|
+
"- 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)."
|
|
581
|
+
);
|
|
582
|
+
lines.push(
|
|
583
|
+
"- Push with `git push -u origin HEAD` (or the current branch name). Do not `git push upstream`."
|
|
584
|
+
);
|
|
573
585
|
lines.push(
|
|
574
586
|
"- Derive the PR title and body from what the changes actually do and why \u2014 inspect the diff/commits and the user request. Do not use the soccer-team worktree nickname or placeholder branch as the PR title."
|
|
575
587
|
);
|
|
@@ -583,9 +595,13 @@ function formatWorktreeDirective(thread) {
|
|
|
583
595
|
lines.push(
|
|
584
596
|
`- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
|
|
585
597
|
);
|
|
598
|
+
} else if (opts?.githubSlug) {
|
|
599
|
+
lines.push(
|
|
600
|
+
`- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name.`
|
|
601
|
+
);
|
|
586
602
|
} else {
|
|
587
603
|
lines.push(
|
|
588
|
-
"- Prefer a draft PR first: `gh pr create --draft
|
|
604
|
+
"- Prefer a draft PR first: `gh pr create --draft -R <origin-owner/name>` (or update via `gh pr edit -R \u2026`) once the change set is coherent. Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree \u2014 never from `upstream`. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name."
|
|
589
605
|
);
|
|
590
606
|
}
|
|
591
607
|
return lines.join("\n");
|
|
@@ -2257,7 +2273,7 @@ async function createThread(input, onSetupLine) {
|
|
|
2257
2273
|
return readThread(thread.id) ?? thread;
|
|
2258
2274
|
}
|
|
2259
2275
|
async function listLinearIssues(agent, repoPath) {
|
|
2260
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
2276
|
+
const { getAdapter: getAdapter2 } = await import("./agents-2XMZO3CY.js");
|
|
2261
2277
|
await requireAgent(agent, { requireLinear: true });
|
|
2262
2278
|
const adapter = getAdapter2(agent);
|
|
2263
2279
|
if (!adapter.listLinearIssues) {
|
|
@@ -2473,7 +2489,7 @@ async function adoptThread(input) {
|
|
|
2473
2489
|
messages: input.messages ?? []
|
|
2474
2490
|
});
|
|
2475
2491
|
writeThread(thread);
|
|
2476
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
2492
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-JBWIRU55.js");
|
|
2477
2493
|
await ensureWorkspace2(repoPath);
|
|
2478
2494
|
return thread;
|
|
2479
2495
|
}
|
|
@@ -3195,7 +3211,11 @@ var Orchestrator = class {
|
|
|
3195
3211
|
}
|
|
3196
3212
|
const isBrightsy = fresh.agent === "brightsy";
|
|
3197
3213
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
3198
|
-
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh
|
|
3214
|
+
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
3215
|
+
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
3216
|
+
() => null
|
|
3217
|
+
)
|
|
3218
|
+
});
|
|
3199
3219
|
const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
|
|
3200
3220
|
const { autoRenameBranchEnabled } = await import("./app-settings-BDMLWCWI.js");
|
|
3201
3221
|
const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled() ? formatRenameBranchDirective(fresh, {
|
|
@@ -3839,7 +3859,7 @@ var Orchestrator = class {
|
|
|
3839
3859
|
return setStatus(thread.id, "idle");
|
|
3840
3860
|
}
|
|
3841
3861
|
if (!existsSync10(thread.worktreePath)) {
|
|
3842
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
3862
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-TYI2SANE.js");
|
|
3843
3863
|
const { execa: execa6 } = await import("execa");
|
|
3844
3864
|
const slug = thread.worktreePath.split("/").pop();
|
|
3845
3865
|
const dest = thread.worktreePath;
|
|
@@ -3916,7 +3936,7 @@ async function startOrchestration(opts) {
|
|
|
3916
3936
|
sourceRef: "default",
|
|
3917
3937
|
...createOpts
|
|
3918
3938
|
}).catch(async () => {
|
|
3919
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
3939
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-TYI2SANE.js");
|
|
3920
3940
|
const repo = await resolveRepoRoot2(repoPath);
|
|
3921
3941
|
const def = await resolveDefaultBranch2(repo);
|
|
3922
3942
|
return createThread({
|
|
@@ -4370,7 +4390,7 @@ async function startMcpServer() {
|
|
|
4370
4390
|
);
|
|
4371
4391
|
server.tool(
|
|
4372
4392
|
"create_draft_pr",
|
|
4373
|
-
"Commit dirty changes if needed, push the thread branch, and create/update a DRAFT GitHub PR. Ready-for-review / non-draft land stays human-only (CLI/app confirm_land). Prefer this when the orchestrator should open a PR itself; alternatively send_to_thread asking the worktree agent to run `gh pr create --draft
|
|
4393
|
+
"Commit dirty changes if needed, push the thread branch to origin, and create/update a DRAFT GitHub PR against that worktree's origin (never upstream). Ready-for-review / non-draft land stays human-only (CLI/app confirm_land). Prefer this when the orchestrator should open a PR itself; alternatively send_to_thread asking the worktree agent to run `gh pr create --draft -R <origin-owner/name>`.",
|
|
4374
4394
|
{ ref: z.string() },
|
|
4375
4395
|
async ({ ref }) => {
|
|
4376
4396
|
try {
|
|
@@ -6,8 +6,8 @@ import {
|
|
|
6
6
|
enrichWorkspacesWithGithub,
|
|
7
7
|
ensureGlobalCoordinatorCwd,
|
|
8
8
|
formatWorkspaceInventory
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
9
|
+
} from "./chunk-SNHWAARD.js";
|
|
10
|
+
import "./chunk-LXHSRNJJ.js";
|
|
11
11
|
import "./chunk-HYRHI3QU.js";
|
|
12
12
|
import "./chunk-M37RITA6.js";
|
|
13
13
|
import "./chunk-AJ6ROGD7.js";
|
|
@@ -11,9 +11,9 @@ import {
|
|
|
11
11
|
orchestrationTitleNeedsSoccerNickname,
|
|
12
12
|
orchestratorSessionPoisonedByBuiltins,
|
|
13
13
|
takenTeamSlugsForOrchestration
|
|
14
|
-
} from "./chunk-
|
|
15
|
-
import "./chunk-
|
|
16
|
-
import "./chunk-
|
|
14
|
+
} from "./chunk-5263JXQY.js";
|
|
15
|
+
import "./chunk-SNHWAARD.js";
|
|
16
|
+
import "./chunk-LXHSRNJJ.js";
|
|
17
17
|
import "./chunk-HYRHI3QU.js";
|
|
18
18
|
import {
|
|
19
19
|
globalAgentCwd
|