@sideboard-ai/core 0.1.81 → 0.1.83
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/cursor-runner.cjs +18 -0
- package/dist/agents/cursor-runner.js +4 -0
- package/dist/{agents-UQ7D6U6L.js → agents-3YPUZME7.js} +6 -5
- package/dist/{agents-EBKJ55PN.js → agents-4KRD46KG.js} +5 -5
- package/dist/{app-settings-NILNWNNQ.js → app-settings-GVSOIJLZ.js} +1 -1
- package/dist/{app-settings-6IOQYGBK.js → app-settings-MQXL7OUF.js} +2 -1
- package/dist/{chunk-P5VDPGAN.js → chunk-DJFGX4RT.js} +3 -3
- package/dist/{chunk-CQBQWX73.js → chunk-E2MIA7DO.js} +8 -3
- package/dist/{chunk-4HJK57XU.js → chunk-ERJS3ZDP.js} +8 -3
- package/dist/{chunk-YVVXWWCC.js → chunk-GD2FM6FN.js} +81 -49
- package/dist/{chunk-FUUVPN4A.js → chunk-HBBXS2FR.js} +78 -49
- package/dist/chunk-IZ7RPF54.js +36 -0
- package/dist/{chunk-4AVU4QXO.js → chunk-JMRJ4F5B.js} +19 -8
- package/dist/{chunk-XNECBC6T.js → chunk-JW6YFPQE.js} +20 -7
- package/dist/{chunk-K553XK7M.js → chunk-LVTNWH7B.js} +2 -2
- package/dist/{chunk-6F2TQFJE.js → chunk-NXXT5SE3.js} +3 -3
- package/dist/{chunk-TDJ43HUD.js → chunk-RS54WYYH.js} +2 -2
- package/dist/{chunk-XKNBSYA7.js → chunk-UHGN4KCL.js} +35 -1
- package/dist/{chunk-IFPN6TER.js → chunk-YO3CYL6B.js} +4 -1
- package/dist/{coordinator-prompt-JQF72JKX.js → coordinator-prompt-46JE4NQR.js} +4 -3
- package/dist/{coordinator-prompt-NYNEFKIV.js → coordinator-prompt-6ICA54JR.js} +3 -3
- package/dist/{global-workspace-DZM4ZFGU.js → global-workspace-GSLCEB5E.js} +5 -4
- package/dist/{global-workspace-NUMUJRWG.js → global-workspace-OBRWUPZG.js} +4 -4
- package/dist/index.cjs +182 -77
- package/dist/index.d.cts +36 -9
- package/dist/index.d.ts +36 -9
- package/dist/index.js +67 -43
- package/dist/mcp/run-stdio.cjs +180 -77
- package/dist/mcp/run-stdio.js +59 -42
- package/dist/{workspaces-QLRCOXAY.js → workspaces-7B3PTEF4.js} +6 -5
- package/dist/{workspaces-SUU2GO3A.js → workspaces-RJIWQB6J.js} +5 -5
- package/dist/{worktree-5VLLFI5W.js → worktree-HSN5LWY6.js} +3 -2
- package/dist/{worktree-UNSOCYZU.js → worktree-U3UIID2K.js} +2 -2
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -31,6 +31,43 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
mod
|
|
32
32
|
));
|
|
33
33
|
|
|
34
|
+
// src/hook/nested-electron-env.ts
|
|
35
|
+
function isNestedElectronEnvKey(key) {
|
|
36
|
+
return NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix));
|
|
37
|
+
}
|
|
38
|
+
function stripNestedElectronEnv(env) {
|
|
39
|
+
const out = { ...env };
|
|
40
|
+
for (const key of Object.keys(out)) {
|
|
41
|
+
if (isNestedElectronEnvKey(key)) delete out[key];
|
|
42
|
+
}
|
|
43
|
+
return out;
|
|
44
|
+
}
|
|
45
|
+
function dropNestedElectronEnvFromProcess(env = process.env) {
|
|
46
|
+
for (const key of Object.keys(env)) {
|
|
47
|
+
if (isNestedElectronEnvKey(key)) delete env[key];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function wrapElectronAsNodeLaunch(file, args) {
|
|
51
|
+
if (process.platform === "win32") return { file, args };
|
|
52
|
+
return {
|
|
53
|
+
file: "/bin/sh",
|
|
54
|
+
args: ["-c", STRIP_NESTED_ELECTRON_THEN_EXEC, "sh", file, ...args]
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
var NESTED_ELECTRON_ENV_PREFIXES, STRIP_NESTED_ELECTRON_THEN_EXEC;
|
|
58
|
+
var init_nested_electron_env = __esm({
|
|
59
|
+
"src/hook/nested-electron-env.ts"() {
|
|
60
|
+
"use strict";
|
|
61
|
+
NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
|
|
62
|
+
STRIP_NESTED_ELECTRON_THEN_EXEC = [
|
|
63
|
+
"vars=`printenv | awk -F= '/^(ELECTRON_|CHROME_)/{print $1}'`",
|
|
64
|
+
'[ -n "$vars" ] && unset $vars',
|
|
65
|
+
"export ELECTRON_RUN_AS_NODE=1",
|
|
66
|
+
'exec "$@"'
|
|
67
|
+
].join("; ");
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
|
|
34
71
|
// src/hook/settings.ts
|
|
35
72
|
function expandHome(path) {
|
|
36
73
|
if (path.startsWith("~/") || path === "~") {
|
|
@@ -1649,6 +1686,19 @@ function formatGhLandError(raw, opts) {
|
|
|
1649
1686
|
}
|
|
1650
1687
|
return detail || "Failed to create or update pull request";
|
|
1651
1688
|
}
|
|
1689
|
+
function isPrNotMergeableError(text3) {
|
|
1690
|
+
return /not mergeable|cannot be cleanly created|cannot merge cleanly|Merge conflict|\bCONFLICTING\b|must be (updated|rebased)|branch is out of date|needs? to be (updated|rebased)|Resolve conflicts or update the branch/i.test(
|
|
1691
|
+
text3
|
|
1692
|
+
);
|
|
1693
|
+
}
|
|
1694
|
+
function formatMergePrError(raw) {
|
|
1695
|
+
const trimmed = raw.trim();
|
|
1696
|
+
if (!trimmed) return "gh pr merge failed";
|
|
1697
|
+
if (isPrNotMergeableError(trimmed)) {
|
|
1698
|
+
return "This pull request cannot merge cleanly into the base branch. Resolve conflicts or update the branch, then retry.";
|
|
1699
|
+
}
|
|
1700
|
+
return extractGhErrorDetail(trimmed) || trimmed;
|
|
1701
|
+
}
|
|
1652
1702
|
var init_gh_errors = __esm({
|
|
1653
1703
|
"src/git/gh-errors.ts"() {
|
|
1654
1704
|
"use strict";
|
|
@@ -2855,7 +2905,7 @@ function applyAppEnvironment(target = process.env, settings = loadAppSettings())
|
|
|
2855
2905
|
}
|
|
2856
2906
|
function childEnvWithAppSettings(extra) {
|
|
2857
2907
|
const settings = loadAppSettings();
|
|
2858
|
-
const env = { ...process.env };
|
|
2908
|
+
const env = stripNestedElectronEnv({ ...process.env });
|
|
2859
2909
|
applyAppEnvironment(env, settings);
|
|
2860
2910
|
if (extra) {
|
|
2861
2911
|
for (const [k, v] of Object.entries(extra)) {
|
|
@@ -2876,6 +2926,7 @@ var init_app_settings = __esm({
|
|
|
2876
2926
|
import_node_os4 = require("os");
|
|
2877
2927
|
import_node_path10 = require("path");
|
|
2878
2928
|
init_thinking_effort();
|
|
2929
|
+
init_nested_electron_env();
|
|
2879
2930
|
init_paths();
|
|
2880
2931
|
init_private_file();
|
|
2881
2932
|
init_secret_vault();
|
|
@@ -3615,6 +3666,41 @@ ${result.stderr}`;
|
|
|
3615
3666
|
].slice(0, 20) : [];
|
|
3616
3667
|
return { conflicting, base: baseName, files };
|
|
3617
3668
|
}
|
|
3669
|
+
async function probeLocalMergeGate(cwd, gate) {
|
|
3670
|
+
const mergeable = (gate?.mergeable ?? "").toUpperCase();
|
|
3671
|
+
const mergeState = (gate?.mergeStateStatus ?? "").toUpperCase();
|
|
3672
|
+
const alreadyConflicting = mergeable === "CONFLICTING" || mergeState === "DIRTY";
|
|
3673
|
+
const inQueue = gate ? prIsInMergeQueue(gate) : false;
|
|
3674
|
+
if (alreadyConflicting || inQueue) return { gate, files: [] };
|
|
3675
|
+
try {
|
|
3676
|
+
const local = await detectLocalMergeConflicts(cwd, gate?.baseRefName ?? null);
|
|
3677
|
+
if (local.conflicting) {
|
|
3678
|
+
return {
|
|
3679
|
+
gate: {
|
|
3680
|
+
mergeable: "CONFLICTING",
|
|
3681
|
+
mergeStateStatus: "DIRTY",
|
|
3682
|
+
reviewDecision: gate?.reviewDecision ?? null,
|
|
3683
|
+
baseRefName: local.base,
|
|
3684
|
+
url: gate?.url ?? null,
|
|
3685
|
+
isInMergeQueue: false
|
|
3686
|
+
},
|
|
3687
|
+
files: local.files
|
|
3688
|
+
};
|
|
3689
|
+
}
|
|
3690
|
+
if (gate && (mergeable === "UNKNOWN" || mergeState === "UNKNOWN")) {
|
|
3691
|
+
return {
|
|
3692
|
+
gate: {
|
|
3693
|
+
...gate,
|
|
3694
|
+
mergeable: gate.mergeable === "UNKNOWN" ? "MERGEABLE" : gate.mergeable,
|
|
3695
|
+
mergeStateStatus: gate.mergeStateStatus === "UNKNOWN" ? "CLEAN" : gate.mergeStateStatus
|
|
3696
|
+
},
|
|
3697
|
+
files: []
|
|
3698
|
+
};
|
|
3699
|
+
}
|
|
3700
|
+
} catch {
|
|
3701
|
+
}
|
|
3702
|
+
return { gate, files: [] };
|
|
3703
|
+
}
|
|
3618
3704
|
async function getPrChecks(cwd, selector) {
|
|
3619
3705
|
const slug = await resolveGithubRepoSlug(cwd);
|
|
3620
3706
|
const args = [
|
|
@@ -3650,47 +3736,9 @@ async function getPrChecks(cwd, selector) {
|
|
|
3650
3736
|
}
|
|
3651
3737
|
}
|
|
3652
3738
|
let gate = await fetchPrMergeGate(cwd, selector, slug);
|
|
3653
|
-
const
|
|
3654
|
-
|
|
3655
|
-
const
|
|
3656
|
-
const inQueue = gate ? prIsInMergeQueue(gate) : false;
|
|
3657
|
-
const needsLocalProbe = !alreadyConflicting && !inQueue;
|
|
3658
|
-
if (needsLocalProbe) {
|
|
3659
|
-
try {
|
|
3660
|
-
const local = await detectLocalMergeConflicts(cwd, gate?.baseRefName ?? null);
|
|
3661
|
-
if (local.conflicting) {
|
|
3662
|
-
const fileHint = local.files.length > 0 ? ` Conflicting paths: ${local.files.slice(0, 8).join(", ")}${local.files.length > 8 ? "\u2026" : ""}.` : "";
|
|
3663
|
-
gate = {
|
|
3664
|
-
mergeable: "CONFLICTING",
|
|
3665
|
-
mergeStateStatus: "DIRTY",
|
|
3666
|
-
reviewDecision: gate?.reviewDecision ?? null,
|
|
3667
|
-
baseRefName: local.base,
|
|
3668
|
-
url: gate?.url ?? null,
|
|
3669
|
-
isInMergeQueue: false
|
|
3670
|
-
};
|
|
3671
|
-
const ciFailed2 = ciChecks.some((c) => c.bucket === "fail");
|
|
3672
|
-
const review2 = (gate.reviewDecision ?? "").toUpperCase();
|
|
3673
|
-
const hasReviewRow2 = review2 === "CHANGES_REQUESTED" || review2 === "REVIEW_REQUIRED";
|
|
3674
|
-
const gateRows2 = buildMergeGateChecks(gate, {
|
|
3675
|
-
suppressGenericBlocked: ciFailed2 || hasReviewRow2
|
|
3676
|
-
}).map(
|
|
3677
|
-
(row) => row.kind === "mergeability" && row.name === "Merge conflicts" ? {
|
|
3678
|
-
...row,
|
|
3679
|
-
description: `${row.description ?? ""}${fileHint}`.trim()
|
|
3680
|
-
} : row
|
|
3681
|
-
);
|
|
3682
|
-
return [...gateRows2, ...ciChecks];
|
|
3683
|
-
}
|
|
3684
|
-
if (gate && (mergeable === "UNKNOWN" || mergeState === "UNKNOWN")) {
|
|
3685
|
-
gate = {
|
|
3686
|
-
...gate,
|
|
3687
|
-
mergeable: gate.mergeable === "UNKNOWN" ? "MERGEABLE" : gate.mergeable,
|
|
3688
|
-
mergeStateStatus: gate.mergeStateStatus === "UNKNOWN" ? "CLEAN" : gate.mergeStateStatus
|
|
3689
|
-
};
|
|
3690
|
-
}
|
|
3691
|
-
} catch {
|
|
3692
|
-
}
|
|
3693
|
-
}
|
|
3739
|
+
const probed = await probeLocalMergeGate(cwd, gate);
|
|
3740
|
+
gate = probed.gate;
|
|
3741
|
+
const fileHint = probed.files.length > 0 ? ` Conflicting paths: ${probed.files.slice(0, 8).join(", ")}${probed.files.length > 8 ? "\u2026" : ""}.` : "";
|
|
3694
3742
|
if (!gate) {
|
|
3695
3743
|
return ciChecks;
|
|
3696
3744
|
}
|
|
@@ -3700,7 +3748,12 @@ async function getPrChecks(cwd, selector) {
|
|
|
3700
3748
|
const gateRows = buildMergeGateChecks(gate, {
|
|
3701
3749
|
// Avoid duplicating "blocked" when CI failures or review rows already explain it.
|
|
3702
3750
|
suppressGenericBlocked: ciFailed || hasReviewRow
|
|
3703
|
-
})
|
|
3751
|
+
}).map(
|
|
3752
|
+
(row) => fileHint && row.kind === "mergeability" && row.name === "Merge conflicts" ? {
|
|
3753
|
+
...row,
|
|
3754
|
+
description: `${row.description ?? ""}${fileHint}`.trim()
|
|
3755
|
+
} : row
|
|
3756
|
+
);
|
|
3704
3757
|
return [...gateRows, ...ciChecks];
|
|
3705
3758
|
}
|
|
3706
3759
|
async function getPrMeta(cwd, selector) {
|
|
@@ -3710,7 +3763,7 @@ async function getPrMeta(cwd, selector) {
|
|
|
3710
3763
|
"view",
|
|
3711
3764
|
selector,
|
|
3712
3765
|
"--json",
|
|
3713
|
-
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus"
|
|
3766
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,isInMergeQueue,mergeStateStatus,mergeable"
|
|
3714
3767
|
];
|
|
3715
3768
|
if (slug) viewArgs.push("--repo", slug);
|
|
3716
3769
|
let { stdout, exitCode, stderr } = await gh(viewArgs, cwd, { reject: false });
|
|
@@ -3720,7 +3773,7 @@ async function getPrMeta(cwd, selector) {
|
|
|
3720
3773
|
"view",
|
|
3721
3774
|
selector,
|
|
3722
3775
|
"--json",
|
|
3723
|
-
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus"
|
|
3776
|
+
"number,title,url,state,isDraft,reviewDecision,baseRefName,headRefName,mergeStateStatus,mergeable"
|
|
3724
3777
|
];
|
|
3725
3778
|
if (slug) retry.push("--repo", slug);
|
|
3726
3779
|
({ stdout, exitCode, stderr } = await gh(retry, cwd, { reject: false }));
|
|
@@ -3731,16 +3784,28 @@ async function getPrMeta(cwd, selector) {
|
|
|
3731
3784
|
}
|
|
3732
3785
|
try {
|
|
3733
3786
|
const view = JSON.parse(stdout);
|
|
3787
|
+
const gate = {
|
|
3788
|
+
mergeable: typeof view.mergeable === "string" && view.mergeable ? view.mergeable : null,
|
|
3789
|
+
mergeStateStatus: typeof view.mergeStateStatus === "string" && view.mergeStateStatus ? view.mergeStateStatus : null,
|
|
3790
|
+
reviewDecision: typeof view.reviewDecision === "string" && view.reviewDecision ? view.reviewDecision : null,
|
|
3791
|
+
baseRefName: String(view.baseRefName ?? ""),
|
|
3792
|
+
url: String(view.url ?? ""),
|
|
3793
|
+
isInMergeQueue: parseInMergeQueue(view)
|
|
3794
|
+
};
|
|
3795
|
+
const probed = await probeLocalMergeGate(cwd, gate);
|
|
3796
|
+
const resolved = probed.gate ?? gate;
|
|
3734
3797
|
return {
|
|
3735
3798
|
number: Number(view.number),
|
|
3736
3799
|
title: String(view.title ?? ""),
|
|
3737
3800
|
url: String(view.url ?? ""),
|
|
3738
3801
|
state: String(view.state ?? ""),
|
|
3739
3802
|
isDraft: Boolean(view.isDraft),
|
|
3740
|
-
reviewDecision:
|
|
3741
|
-
baseRefName: String(view.baseRefName ?? ""),
|
|
3803
|
+
reviewDecision: resolved.reviewDecision,
|
|
3804
|
+
baseRefName: resolved.baseRefName || String(view.baseRefName ?? ""),
|
|
3742
3805
|
headRefName: String(view.headRefName ?? ""),
|
|
3743
|
-
isInMergeQueue:
|
|
3806
|
+
isInMergeQueue: Boolean(resolved.isInMergeQueue),
|
|
3807
|
+
mergeable: resolved.mergeable,
|
|
3808
|
+
mergeStateStatus: resolved.mergeStateStatus
|
|
3744
3809
|
};
|
|
3745
3810
|
} catch {
|
|
3746
3811
|
return null;
|
|
@@ -4208,7 +4273,9 @@ async function mergePr(cwd, selector, opts) {
|
|
|
4208
4273
|
if (slug) args.push("--repo", slug);
|
|
4209
4274
|
const { exitCode, stderr, stdout } = await gh(args, cwd, { reject: false });
|
|
4210
4275
|
if (exitCode !== 0) {
|
|
4211
|
-
throw new Error(
|
|
4276
|
+
throw new Error(
|
|
4277
|
+
formatMergePrError(stderr.trim() || stdout.trim() || "gh pr merge failed")
|
|
4278
|
+
);
|
|
4212
4279
|
}
|
|
4213
4280
|
const after = await gh(viewArgs, cwd, { reject: false });
|
|
4214
4281
|
if (after.exitCode === 0 && after.stdout.trim()) {
|
|
@@ -4603,6 +4670,7 @@ var init_coordinator_prompt = __esm({
|
|
|
4603
4670
|
"- get_pr_stack / open_pr_stack_layers / add_stack_layer / create_pr_stack \u2014 GitHub stacked PRs (`gh stack`); one worktree per layer",
|
|
4604
4671
|
"- list_models \u2014 only when you need a specific model (rare); otherwise omit model so Account defaults apply",
|
|
4605
4672
|
"- list_threads / get_thread \u2014 fleet status (what is going on)",
|
|
4673
|
+
"- ask_user \u2014 multiple-choice questions in the composer (any mode, not only Plan). Explain options in chat first, include a description on every option, then wait for answers.",
|
|
4606
4674
|
"- set_caffeinate \u2014 keep this Mac awake across turns (macOS caffeinate). Turn on for Slack / away-from-keyboard work. Turn OFF when the user says they are done, wrapping up, going to sleep, or no longer need the machine awake. Closing this chat also releases it.",
|
|
4607
4675
|
"Workspaces:",
|
|
4608
4676
|
"- add_workspace / remove_workspace \u2014 register or unregister a git repo",
|
|
@@ -4622,7 +4690,11 @@ var init_coordinator_prompt = __esm({
|
|
|
4622
4690
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .sideboard/review.md when present, else local guidelines; sends "Review changes in this workspace."); then wait_for_turn / get_turn_result on the returned id',
|
|
4623
4691
|
"- ask_git \u2014 commit & push, open a draft PR, resolve conflicts, or merge. When the worktree is clean, Sideboard pushes / opens the PR itself. When dirty, it queues the worktree agent \u2014 then wait_for_turn. Prefer this over paraphrasing.",
|
|
4624
4692
|
'- Merge (`ask_git` action=merge / send_to_thread "Merge PR.") only when the user explicitly asked to merge that PR. Do not merge because the work looks done, CI is green, or a typical flow includes it.',
|
|
4625
|
-
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "
|
|
4693
|
+
'- Or send_to_thread with those exact phrases: "Commit and push.", "Commit, push, and open a draft PR.", "Merge the remote branch (main) into your branch and resolve conflicts. Then, commit and push your changes.", "Merge PR." (draft PRs: `gh pr create --draft -R <origin-owner/name>` using the workspace `github:` slug \u2014 never upstream). Never run git/gh from this orchestration cwd, and never merge the PR yourself.',
|
|
4694
|
+
"Process guides:",
|
|
4695
|
+
"- Recurring multi-item / fan-out: if the child worktree has `.claude/skills/graph-engineering/SKILL.md`, tell the worker to follow it (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch three threads.",
|
|
4696
|
+
"- Recurring shapes: have the worktree agent write `.claude/skills/<kebab-name>/SKILL.md` (commit it) so later threads and native Claude Code / attach see it. Do not use `.sideboard/skills` for new guides. Codex/OpenCode: one line in AGENTS.md pointing at that file.",
|
|
4697
|
+
"- One-offs: no guide. Same miss across threads: edit the skill or `.sideboard/review.md`, then rerun the batch \u2014 do not patch three threads.",
|
|
4626
4698
|
"Human-only (do not attempt): ready-for-review land (confirm_land), purge_thread.",
|
|
4627
4699
|
"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.",
|
|
4628
4700
|
"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."
|
|
@@ -5528,6 +5600,13 @@ var init_profile = __esm({
|
|
|
5528
5600
|
function isAsarPath(filePath) {
|
|
5529
5601
|
return /\.asar([/\\]|$)/.test(filePath);
|
|
5530
5602
|
}
|
|
5603
|
+
function applyNodeLaunch(launch, args) {
|
|
5604
|
+
if (!launch.env.ELECTRON_RUN_AS_NODE) {
|
|
5605
|
+
return { file: launch.file, args, env: launch.env };
|
|
5606
|
+
}
|
|
5607
|
+
const wrapped = wrapElectronAsNodeLaunch(launch.file, args);
|
|
5608
|
+
return { file: wrapped.file, args: wrapped.args, env: launch.env };
|
|
5609
|
+
}
|
|
5531
5610
|
async function resolveNodeLaunch(scriptPath) {
|
|
5532
5611
|
if (isAsarPath(scriptPath)) {
|
|
5533
5612
|
return {
|
|
@@ -5548,6 +5627,7 @@ async function resolveNodeLaunch(scriptPath) {
|
|
|
5548
5627
|
var init_node_launch = __esm({
|
|
5549
5628
|
"src/agents/node-launch.ts"() {
|
|
5550
5629
|
"use strict";
|
|
5630
|
+
init_nested_electron_env();
|
|
5551
5631
|
init_run();
|
|
5552
5632
|
}
|
|
5553
5633
|
});
|
|
@@ -5674,11 +5754,11 @@ async function resolveSideboardMcpServer() {
|
|
|
5674
5754
|
if (entry) {
|
|
5675
5755
|
const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
|
|
5676
5756
|
const scriptArgs = isCli ? [entry, "mcp"] : [entry];
|
|
5677
|
-
const launch = await resolveNodeLaunch(entry);
|
|
5757
|
+
const launch = applyNodeLaunch(await resolveNodeLaunch(entry), scriptArgs);
|
|
5678
5758
|
return {
|
|
5679
5759
|
name: "sideboard",
|
|
5680
5760
|
command: launch.file,
|
|
5681
|
-
args:
|
|
5761
|
+
args: launch.args,
|
|
5682
5762
|
...Object.keys(launch.env).length > 0 ? { env: launch.env } : {}
|
|
5683
5763
|
};
|
|
5684
5764
|
}
|
|
@@ -6883,10 +6963,13 @@ var init_cursor = __esm({
|
|
|
6883
6963
|
};
|
|
6884
6964
|
const runner = cursorRunnerPath();
|
|
6885
6965
|
const isTs = runner.endsWith(".ts");
|
|
6886
|
-
const launch =
|
|
6966
|
+
const launch = applyNodeLaunch(
|
|
6967
|
+
await resolveNodeLaunch(runner),
|
|
6968
|
+
isTs ? ["--import", "tsx", runner] : [runner]
|
|
6969
|
+
);
|
|
6887
6970
|
return {
|
|
6888
6971
|
file: launch.file,
|
|
6889
|
-
args:
|
|
6972
|
+
args: launch.args,
|
|
6890
6973
|
cwd: thread.worktreePath,
|
|
6891
6974
|
stdin: JSON.stringify(req),
|
|
6892
6975
|
env: {
|
|
@@ -8175,6 +8258,9 @@ var init_cursor_recover = __esm({
|
|
|
8175
8258
|
}
|
|
8176
8259
|
});
|
|
8177
8260
|
|
|
8261
|
+
// src/mcp/run-stdio.ts
|
|
8262
|
+
init_nested_electron_env();
|
|
8263
|
+
|
|
8178
8264
|
// src/mcp/server.ts
|
|
8179
8265
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
8180
8266
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
@@ -9150,7 +9236,8 @@ function agentGitPrompt(action, opts) {
|
|
|
9150
9236
|
return "Commit, push, and open a PR in the browser.";
|
|
9151
9237
|
case "resolve-conflicts": {
|
|
9152
9238
|
const base = opts?.prBase?.trim().replace(/^refs\/heads\//, "");
|
|
9153
|
-
|
|
9239
|
+
const named = base ? ` (${base})` : "";
|
|
9240
|
+
return `Merge the remote branch${named} into your branch and resolve conflicts. Then, commit and push your changes.`;
|
|
9154
9241
|
}
|
|
9155
9242
|
case "merge":
|
|
9156
9243
|
return "Merge PR.";
|
|
@@ -9178,6 +9265,8 @@ var import_node_path18 = require("path");
|
|
|
9178
9265
|
var import_execa3 = require("execa");
|
|
9179
9266
|
var import_node_readline2 = require("readline");
|
|
9180
9267
|
init_settings();
|
|
9268
|
+
init_nested_electron_env();
|
|
9269
|
+
init_nested_electron_env();
|
|
9181
9270
|
var PORT_RANGE_SIZE = 10;
|
|
9182
9271
|
function matchSimpleGlob(pattern, name) {
|
|
9183
9272
|
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
@@ -9261,16 +9350,6 @@ async function captureLoginEnv() {
|
|
|
9261
9350
|
cachedLoginEnv = { ...process.env };
|
|
9262
9351
|
return { ...cachedLoginEnv };
|
|
9263
9352
|
}
|
|
9264
|
-
var NESTED_ELECTRON_ENV_PREFIXES = ["ELECTRON_", "CHROME_"];
|
|
9265
|
-
function stripNestedElectronEnv(env) {
|
|
9266
|
-
const out = { ...env };
|
|
9267
|
-
for (const key of Object.keys(out)) {
|
|
9268
|
-
if (NESTED_ELECTRON_ENV_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
|
9269
|
-
delete out[key];
|
|
9270
|
-
}
|
|
9271
|
-
}
|
|
9272
|
-
return out;
|
|
9273
|
-
}
|
|
9274
9353
|
function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
9275
9354
|
const env = stripNestedElectronEnv({
|
|
9276
9355
|
...baseEnv ?? process.env
|
|
@@ -10421,6 +10500,10 @@ File: src/client/frontends/desktop/core/UserData.ts
|
|
|
10421
10500
|
|
|
10422
10501
|
**Approve** \u2014 Diff is scoped, behavior looks correct, and there are no blocking issues. Safe to merge.
|
|
10423
10502
|
</example>
|
|
10503
|
+
|
|
10504
|
+
## Growing the rules
|
|
10505
|
+
|
|
10506
|
+
If a blocking issue is a missing or ambiguous repo rule that will recur, say so and propose one sentence for \`.sideboard/review.md\` or a \`.claude/skills/<name>/SKILL.md\`. Do not only patch this diff when the same miss will happen again. New skills go under \`.claude/skills\` (Claude Code / attach) \u2014 not \`.sideboard/skills\`.
|
|
10424
10507
|
`;
|
|
10425
10508
|
|
|
10426
10509
|
// src/review/request-review.ts
|
|
@@ -12590,7 +12673,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
12590
12673
|
'- "Fix CI: <name>." \u2192 investigate that failing check, fix it, commit, and push.'
|
|
12591
12674
|
);
|
|
12592
12675
|
lines.push(
|
|
12593
|
-
'- "
|
|
12676
|
+
'- "Merge the remote branch (<base>) into your branch and resolve conflicts. Then, commit and push your changes." \u2192 fetch the PR base, merge it into this branch, resolve conflicts carefully, commit, and push until the PR is mergeable.'
|
|
12594
12677
|
);
|
|
12595
12678
|
lines.push(
|
|
12596
12679
|
'- "Address review comments." \u2192 read PR review feedback, make the requested changes, commit, and push.'
|
|
@@ -12598,11 +12681,22 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
12598
12681
|
lines.push(
|
|
12599
12682
|
'- "Merge PR." \u2192 merge this thread\'s open pull request on GitHub (this phrase is the explicit ask). 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.'
|
|
12600
12683
|
);
|
|
12684
|
+
lines.push("");
|
|
12685
|
+
lines.push(formatProcessGuideDirective());
|
|
12601
12686
|
return lines.join("\n");
|
|
12602
12687
|
}
|
|
12603
12688
|
function formatWorktreeReminder() {
|
|
12604
12689
|
return "Sideboard worktree: 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.";
|
|
12605
12690
|
}
|
|
12691
|
+
function formatProcessGuideDirective() {
|
|
12692
|
+
return [
|
|
12693
|
+
"Process guides (recurring work only):",
|
|
12694
|
+
"- If `.claude/skills/graph-engineering/SKILL.md` exists, follow it (`/graph-engineering`) for migrations, ports, batch fixes, and other fan-out. Judge first; state on disk; grow the rulebook; do not patch around it.",
|
|
12695
|
+
"- If this same shape of work will happen again, write `.claude/skills/<kebab-name>/SKILL.md` in this worktree (Claude Code project skill). Sideboard `/name`, Claude Code, and `attach` all load that path. Do not leave the method only in chat.",
|
|
12696
|
+
"- Do not write new skills under `.sideboard/skills` \u2014 native agents do not scan it. Point Codex/OpenCode at the file from `AGENTS.md`. Optional: symlink `.cursor/skills/<name>` to the Claude skill.",
|
|
12697
|
+
"- Skip a guide for a one-off. If a matching skill exists, follow it. Same miss twice \u2192 edit the skill (or `.sideboard/review.md`), do not patch around it."
|
|
12698
|
+
].join("\n");
|
|
12699
|
+
}
|
|
12606
12700
|
function formatArtifactDirective() {
|
|
12607
12701
|
return [
|
|
12608
12702
|
"Sideboard side column (desktop UI):",
|
|
@@ -12620,9 +12714,22 @@ function formatArtifactDirective() {
|
|
|
12620
12714
|
"Files / media browser (CMS file manager column):",
|
|
12621
12715
|
"4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
|
|
12622
12716
|
" Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
|
|
12623
|
-
"
|
|
12717
|
+
"Multiple-choice questions (any mode \u2014 not only Plan):",
|
|
12718
|
+
"5) Call Sideboard MCP `ask_user` when the user should pick from predefined options (approach forks, requirements, which API). First write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it). Include a description on every option. After calling, stop and wait for their next message with answers. Do not ask multiple-choice questions as plain chat bullets \u2014 use ask_user so Sideboard shows the composer picker.",
|
|
12719
|
+
"Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages; ask_user for predefined-option questions."
|
|
12624
12720
|
].join("\n");
|
|
12625
12721
|
}
|
|
12722
|
+
function formatUiReminder() {
|
|
12723
|
+
return [
|
|
12724
|
+
"Sideboard side column (important):",
|
|
12725
|
+
"There is no claude.ai Artifact tool here \u2014 that is normal.",
|
|
12726
|
+
"HTML/SVG/markdown: ```html fence or MCP present_artifact.",
|
|
12727
|
+
"CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
|
|
12728
|
+
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
12729
|
+
"Do not say artifacts/CMS UI are unavailable.",
|
|
12730
|
+
"Multiple-choice questions: MCP ask_user (composer picker, any mode). Explain options in chat first, then wait for answers."
|
|
12731
|
+
].join(" ");
|
|
12732
|
+
}
|
|
12626
12733
|
|
|
12627
12734
|
// src/orchestrator/orchestrator.ts
|
|
12628
12735
|
init_types();
|
|
@@ -13166,14 +13273,7 @@ var Orchestrator = class {
|
|
|
13166
13273
|
SLACK_REPLY_FORMATTING
|
|
13167
13274
|
].join("\n") : null
|
|
13168
13275
|
].filter(Boolean).join("\n") : null;
|
|
13169
|
-
const artifactReminder = thread.agent !== "brightsy" ?
|
|
13170
|
-
"Sideboard side column (important):",
|
|
13171
|
-
"There is no claude.ai Artifact tool here \u2014 that is normal.",
|
|
13172
|
-
"HTML/SVG/markdown: ```html fence or MCP present_artifact.",
|
|
13173
|
-
"CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
|
|
13174
|
-
"Files column: MCP present_files (brightsy account storage or memory).",
|
|
13175
|
-
"Do not say artifacts/CMS UI are unavailable."
|
|
13176
|
-
].join(" ") : null;
|
|
13276
|
+
const artifactReminder = thread.agent !== "brightsy" ? formatUiReminder() : null;
|
|
13177
13277
|
const worktreeReminder = thread.agent !== "brightsy" && !isOrchestratorThread(thread) ? formatWorktreeReminder() : null;
|
|
13178
13278
|
const slackReplyContext = formatSlackRepliesForTurn(
|
|
13179
13279
|
pendingSlackExternalReplies(thread.messages)
|
|
@@ -13867,7 +13967,9 @@ var Orchestrator = class {
|
|
|
13867
13967
|
reviewDecision: null,
|
|
13868
13968
|
baseRefName: "",
|
|
13869
13969
|
headRefName: "",
|
|
13870
|
-
isInMergeQueue: false
|
|
13970
|
+
isInMergeQueue: false,
|
|
13971
|
+
mergeable: null,
|
|
13972
|
+
mergeStateStatus: null
|
|
13871
13973
|
};
|
|
13872
13974
|
await this.persistPrMetaAndMaybeArchive(thread, metaLike);
|
|
13873
13975
|
return { url: metaLike.url, state };
|
|
@@ -15541,7 +15643,7 @@ async function startMcpServer() {
|
|
|
15541
15643
|
);
|
|
15542
15644
|
server.tool(
|
|
15543
15645
|
"ask_user",
|
|
15544
|
-
"Ask the user clarifying multiple-choice questions in Sideboard\u2019s composer (
|
|
15646
|
+
"Ask the user clarifying multiple-choice questions in Sideboard\u2019s composer (any mode \u2014 not only Plan). Before calling, write a short chat message explaining the decision and what each option means. Include a description on every option. Use when the user should pick from predefined options (approach forks, requirements, which API) \u2014 not for \u201Cis the plan ready?\u201D. After calling, stop and wait for their next message with answers.",
|
|
15545
15647
|
{
|
|
15546
15648
|
questions: import_zod3.z.array(
|
|
15547
15649
|
import_zod3.z.object({
|
|
@@ -16455,6 +16557,7 @@ async function startMcpServer() {
|
|
|
16455
16557
|
}
|
|
16456
16558
|
|
|
16457
16559
|
// src/mcp/run-stdio.ts
|
|
16560
|
+
dropNestedElectronEnvFromProcess();
|
|
16458
16561
|
startMcpServer().catch((err) => {
|
|
16459
16562
|
console.error(err);
|
|
16460
16563
|
process.exitCode = 1;
|