@sideboard-ai/core 0.1.148 → 0.1.150
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/{abletime-QEVAE67D.js → abletime-223A3LY6.js} +2 -2
- package/dist/{abletime-DI55AJX3.js → abletime-CLC5UJC2.js} +2 -2
- package/dist/agents/cursor-runner.cjs +85 -45
- package/dist/agents/cursor-runner.js +47 -12
- package/dist/{agents-DUF4Q2ZI.js → agents-KKXGTEV6.js} +10 -9
- package/dist/{agents-INCTFWKA.js → agents-YWBQXOA2.js} +10 -9
- package/dist/{app-settings-WJDCJFSY.js → app-settings-3CHCNIMD.js} +5 -1
- package/dist/{app-settings-ZCN632OJ.js → app-settings-J3JBCUOT.js} +5 -1
- package/dist/{chunk-I77RYPOH.js → chunk-4XNSGDXE.js} +12 -0
- package/dist/{chunk-KBWND62T.js → chunk-7F4XE6UG.js} +5 -5
- package/dist/{chunk-R4JP32P5.js → chunk-AF6O55PJ.js} +4 -4
- package/dist/{chunk-BOD5V52W.js → chunk-B7XK37WZ.js} +1 -1
- package/dist/{chunk-BGQBELGJ.js → chunk-CZD4NRDZ.js} +12 -0
- package/dist/{chunk-ZVYLEF72.js → chunk-DMRIZR6M.js} +6 -6
- package/dist/{chunk-5MS2XTNV.js → chunk-DXCNW2JF.js} +113 -52
- package/dist/{chunk-KPIYENTF.js → chunk-FNQNJOHY.js} +89 -5
- package/dist/{chunk-ED4UPEJX.js → chunk-G7SIQFBQ.js} +1 -1
- package/dist/{chunk-3QRGCKYL.js → chunk-HAS5EPBS.js} +2 -2
- package/dist/{chunk-WT5HSFOU.js → chunk-HEII7W3Q.js} +5 -2
- package/dist/{chunk-EGDRPA4B.js → chunk-NOTANBYC.js} +6 -6
- package/dist/{chunk-CTXQHSTY.js → chunk-NUPITVRF.js} +134 -73
- package/dist/{chunk-QTUESPAW.js → chunk-PTOSP4AH.js} +1 -1
- package/dist/{chunk-Q62SDB53.js → chunk-QGJHIJHV.js} +2 -2
- package/dist/{chunk-YQRBNOIW.js → chunk-SDN4ZYQH.js} +24 -13
- package/dist/{chunk-DVM4ID64.js → chunk-UFHNSFAS.js} +89 -5
- package/dist/{chunk-N3VNOFXQ.js → chunk-VO4SPEBS.js} +4 -4
- package/dist/chunk-VSFGPWCQ.js +62 -0
- package/dist/{chunk-N5PM7HGQ.js → chunk-W6N6GQME.js} +1 -1
- package/dist/{chunk-FKOIHGKV.js → chunk-WHU7YGWP.js} +1 -1
- package/dist/{chunk-VZJVKQHH.js → chunk-WLV7TRMR.js} +1 -1
- package/dist/chunk-Y4NAPW5I.js +60 -0
- package/dist/{chunk-B3SJXYIJ.js → chunk-Y7YBWWIG.js} +1 -1
- package/dist/{chunk-XOKHXFFX.js → chunk-YGGBJY5A.js} +22 -8
- package/dist/{chunk-JTPDWTWJ.js → chunk-Z2PVJKMN.js} +137 -114
- package/dist/{chunk-YP3CSOZ6.js → chunk-ZGFYFVJF.js} +142 -114
- package/dist/{connected-teams-IJUJQ7R6.js → connected-teams-I2WZZZFA.js} +2 -2
- package/dist/{connected-teams-4A2AXDNN.js → connected-teams-XO766HB4.js} +2 -2
- package/dist/{coordinator-prompt-ZWBMAIWA.js → coordinator-prompt-NYR5TPBD.js} +6 -5
- package/dist/{coordinator-prompt-5GXGBGEZ.js → coordinator-prompt-UCQJTFA7.js} +6 -5
- package/dist/{global-workspace-2SIPM4PW.js → global-workspace-4QHDAD2D.js} +7 -6
- package/dist/{global-workspace-OJRXWXEA.js → global-workspace-4SENNWBU.js} +7 -6
- package/dist/index.cjs +1002 -575
- package/dist/index.d.cts +91 -10
- package/dist/index.d.ts +91 -10
- package/dist/index.js +268 -93
- package/dist/mcp/run-stdio.cjs +980 -580
- package/dist/mcp/run-stdio.js +196 -43
- package/dist/{orchestrator-OVYITCO6.js → orchestrator-GZE4X3XV.js} +14 -11
- package/dist/{orchestrator-NWIU5TJP.js → orchestrator-QSBRWME5.js} +16 -13
- package/dist/{plan-file-6O7G4VPQ.js → plan-file-5S5TUNAW.js} +2 -2
- package/dist/{plan-file-PHVKUAEE.js → plan-file-IBSU2PVW.js} +2 -2
- package/dist/{run-XQKGHQZ2.js → run-CAGKZLHA.js} +1 -1
- package/dist/{run-USF6FRKV.js → run-EBWL2Q4N.js} +1 -1
- package/dist/{workspaces-UUJNOO4T.js → workspaces-7S7QKCUE.js} +8 -7
- package/dist/{workspaces-3NUUZTQK.js → workspaces-RDUSB6FD.js} +8 -7
- package/dist/{worktree-RZRJNHYL.js → worktree-63AGPPLO.js} +5 -4
- package/dist/{worktree-UCWWTVLS.js → worktree-JIZ3QMZX.js} +5 -4
- package/dist/worktree-exclude-6MQWGWV5.js +11 -0
- package/dist/worktree-exclude-TV6EV6BS.js +9 -0
- package/package.json +1 -1
|
@@ -99,17 +99,93 @@ function withExportedPath(command, pathValue) {
|
|
|
99
99
|
return `export PATH=${posixShellSingleQuote(pathValue)} && ${trimmed}`;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
+
// src/git/github-agent-auth.ts
|
|
103
|
+
import { chmodSync, existsSync as existsSync2, mkdirSync, writeFileSync } from "fs";
|
|
104
|
+
import { homedir as homedir2 } from "os";
|
|
105
|
+
import { dirname, join as join2 } from "path";
|
|
106
|
+
function githubAgentAuthDir() {
|
|
107
|
+
const override = process.env.SIDEBOARD_GIT_AUTH_DIR?.trim();
|
|
108
|
+
if (override) return override;
|
|
109
|
+
return join2(homedir2(), ".sideboard-git-auth");
|
|
110
|
+
}
|
|
111
|
+
function githubCredentialStorePath() {
|
|
112
|
+
return join2(githubAgentAuthDir(), "git-credentials");
|
|
113
|
+
}
|
|
114
|
+
function githubGhConfigDir() {
|
|
115
|
+
return join2(githubAgentAuthDir(), "gh");
|
|
116
|
+
}
|
|
117
|
+
function writePrivateFile(file, body) {
|
|
118
|
+
mkdirSync(dirname(file), { recursive: true, mode: 448 });
|
|
119
|
+
try {
|
|
120
|
+
chmodSync(dirname(file), 448);
|
|
121
|
+
} catch {
|
|
122
|
+
}
|
|
123
|
+
writeFileSync(file, body, { encoding: "utf8", mode: 384 });
|
|
124
|
+
try {
|
|
125
|
+
chmodSync(file, 384);
|
|
126
|
+
} catch {
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function gitCredentialStoreContents(token) {
|
|
130
|
+
return `https://x-access-token:${encodeURIComponent(token)}@github.com
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
function ghHostsYml(token, user = "x-access-token") {
|
|
134
|
+
const u = user.replace(/[^A-Za-z0-9._-]/g, "") || "x-access-token";
|
|
135
|
+
return [
|
|
136
|
+
"github.com:",
|
|
137
|
+
" git_protocol: https",
|
|
138
|
+
` user: ${u}`,
|
|
139
|
+
` oauth_token: ${token}`,
|
|
140
|
+
" users:",
|
|
141
|
+
` ${u}:`,
|
|
142
|
+
` oauth_token: ${token}`,
|
|
143
|
+
""
|
|
144
|
+
].join("\n");
|
|
145
|
+
}
|
|
146
|
+
function materializeGithubAgentAuth(token, user) {
|
|
147
|
+
const trimmed = token.trim();
|
|
148
|
+
if (!trimmed) return;
|
|
149
|
+
const root = githubAgentAuthDir();
|
|
150
|
+
mkdirSync(root, { recursive: true, mode: 448 });
|
|
151
|
+
try {
|
|
152
|
+
chmodSync(root, 448);
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
writePrivateFile(githubCredentialStorePath(), gitCredentialStoreContents(trimmed));
|
|
156
|
+
const ghDir = githubGhConfigDir();
|
|
157
|
+
mkdirSync(ghDir, { recursive: true, mode: 448 });
|
|
158
|
+
writePrivateFile(join2(ghDir, "hosts.yml"), ghHostsYml(trimmed, user));
|
|
159
|
+
writePrivateFile(join2(ghDir, "config.yml"), "git_protocol: https\nprompt: disabled\n");
|
|
160
|
+
}
|
|
161
|
+
function githubAgentAuthReady() {
|
|
162
|
+
return existsSync2(githubCredentialStorePath()) && existsSync2(join2(githubGhConfigDir(), "hosts.yml"));
|
|
163
|
+
}
|
|
164
|
+
function githubCredentialHelperGitConfig() {
|
|
165
|
+
const file = githubCredentialStorePath();
|
|
166
|
+
return [
|
|
167
|
+
{ key: "credential.helper", value: "" },
|
|
168
|
+
{ key: "credential.helper", value: `store --file=${file}` }
|
|
169
|
+
];
|
|
170
|
+
}
|
|
171
|
+
function githubGhConfigEnv() {
|
|
172
|
+
return {
|
|
173
|
+
GH_CONFIG_DIR: githubGhConfigDir(),
|
|
174
|
+
GH_PROMPT_DISABLED: "1"
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
102
178
|
// src/git/stale-lock.ts
|
|
103
|
-
import { existsSync as
|
|
104
|
-
import { join as
|
|
179
|
+
import { existsSync as existsSync3, statSync, unlinkSync } from "fs";
|
|
180
|
+
import { join as join3 } from "path";
|
|
105
181
|
var STALE_INDEX_LOCK_MS = 2e4;
|
|
106
182
|
function isIndexLockError(text) {
|
|
107
183
|
return /Unable to create ['"][^'"]*index\.lock['"]: File exists/i.test(text);
|
|
108
184
|
}
|
|
109
185
|
function clearStaleIndexLock(gitDir, maxAgeMs = STALE_INDEX_LOCK_MS, now = Date.now()) {
|
|
110
|
-
const lockPath =
|
|
186
|
+
const lockPath = join3(gitDir, "index.lock");
|
|
111
187
|
try {
|
|
112
|
-
if (!
|
|
188
|
+
if (!existsSync3(lockPath)) return null;
|
|
113
189
|
if (now - statSync(lockPath).mtimeMs < maxAgeMs) return null;
|
|
114
190
|
unlinkSync(lockPath);
|
|
115
191
|
return lockPath;
|
|
@@ -211,7 +287,10 @@ async function gh(args, cwd, opts) {
|
|
|
211
287
|
timeoutMs: opts?.timeoutMs,
|
|
212
288
|
env: {
|
|
213
289
|
GH_PROMPT_DISABLED: "1",
|
|
214
|
-
GIT_TERMINAL_PROMPT: "0"
|
|
290
|
+
GIT_TERMINAL_PROMPT: "0",
|
|
291
|
+
// Isolated hosts.yml uses git_protocol: https so `gh pr create` does not
|
|
292
|
+
// shell out over SSH when Settings → Git is SSH (ask_git in Electron).
|
|
293
|
+
...githubAgentAuthReady() ? githubGhConfigEnv() : {}
|
|
215
294
|
}
|
|
216
295
|
});
|
|
217
296
|
}
|
|
@@ -230,6 +309,11 @@ export {
|
|
|
230
309
|
posixShellSingleQuote,
|
|
231
310
|
resolveCommandBinarySync,
|
|
232
311
|
withExportedPath,
|
|
312
|
+
githubAgentAuthDir,
|
|
313
|
+
materializeGithubAgentAuth,
|
|
314
|
+
githubAgentAuthReady,
|
|
315
|
+
githubCredentialHelperGitConfig,
|
|
316
|
+
githubGhConfigEnv,
|
|
233
317
|
clearStaleIndexLocks,
|
|
234
318
|
run,
|
|
235
319
|
resolveGitDirsForLockRecovery,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isGlobalRepoPath
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AF6O55PJ.js";
|
|
4
4
|
import {
|
|
5
5
|
ensureGhPreferOrigin,
|
|
6
6
|
resolveRepoRoot
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZGFYFVJF.js";
|
|
8
8
|
import {
|
|
9
9
|
appDataDir
|
|
10
10
|
} from "./chunk-QZQEXME2.js";
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
} from "./chunk-4TR3HZFT.js";
|
|
5
5
|
import {
|
|
6
6
|
run
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UFHNSFAS.js";
|
|
8
8
|
|
|
9
9
|
// src/agents/error-detail.ts
|
|
10
10
|
function formatUnknownDetail(err) {
|
|
@@ -139,7 +139,7 @@ function looksLikeRetryableRunnerCrash(text) {
|
|
|
139
139
|
const lower = text.trim().toLowerCase();
|
|
140
140
|
if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
|
|
141
141
|
if (!lower) return true;
|
|
142
|
-
return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|cursor runner crashed in node|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|connection stalled|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
|
|
142
|
+
return /uv_run|spineventloopinternal|libuv|homebrew node \+ shared libuv|cursor runner crashed in node|hascustomhostobject|electroninitializeicuandstartnode|nested chromium|truncated crash dump|connection stalled|network request failed|cursor startup failed:.+\(retryable\)|sig(?:segv|abrt|ill)|segmentation fault|illegal instruction|fatal error/.test(
|
|
143
143
|
lower
|
|
144
144
|
);
|
|
145
145
|
}
|
|
@@ -207,6 +207,9 @@ function humanizeAgentFailDetail(detail) {
|
|
|
207
207
|
if (/connection stalled/.test(lower)) {
|
|
208
208
|
return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
|
|
209
209
|
}
|
|
210
|
+
if (/network request failed|cursor startup failed:.+\(retryable\)/.test(lower)) {
|
|
211
|
+
return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (a transient Cursor SDK network error).`;
|
|
212
|
+
}
|
|
210
213
|
return raw;
|
|
211
214
|
}
|
|
212
215
|
function turnFailChatText(opts) {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveGithubRepoSlug
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-ZGFYFVJF.js";
|
|
4
4
|
import {
|
|
5
5
|
resolveThreadDefaults
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-4XNSGDXE.js";
|
|
7
7
|
import {
|
|
8
8
|
globalAgentCwd,
|
|
9
9
|
sideboardReposDir
|
|
@@ -45,8 +45,8 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
45
45
|
"Discover:",
|
|
46
46
|
"- list_workspaces \u2014 registered repos (path + github slug when known)",
|
|
47
47
|
"- list_board \u2014 Home Kanban of worktrees (New / Draft / Review / Merged; one card per checkout). Path to merge: no PR \u2192 draft PR \u2192 open PR \u2192 merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats are not on the board. Filters: query, repoPath, kind, column, limit.",
|
|
48
|
-
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear, AbleTime MCP, or GitHub Issues)",
|
|
49
|
-
"- linear_list_teams / linear_get_issue / linear_create_issue / linear_update_issue / linear_comment \u2014 Linear Account connection; call linear_list_teams for team key and workflow states; pass ENG-123 or uuid. linear_get_issue returns comments, relations, parent/children, and the rest of the issue metadata. If mutations fail with a scope error, Disconnect and Connect Linear in Account settings.",
|
|
48
|
+
"- list_branches / list_prs / list_issues \u2014 pass repoPath from list_workspaces (issues: Linear, AbleTime MCP, or GitHub Issues). list_issues accepts query and assignee (me / unassigned / all / user id) so Linear is not limited to tickets assigned to you.",
|
|
49
|
+
"- linear_list_teams / linear_search_issues / linear_get_issue / linear_create_issue / linear_update_issue / linear_comment \u2014 Linear Account connection; call linear_list_teams for team key and workflow states; pass ENG-123 or uuid. linear_search_issues finds unassigned and other people's open issues (assignee=unassigned|all|me|user). linear_get_issue returns comments, relations, parent/children, and the rest of the issue metadata. If mutations fail with a scope error, Disconnect and Connect Linear in Account settings.",
|
|
50
50
|
"- abletime_orientation / abletime_list_projects / abletime_list_tasks / abletime_search_tasks / abletime_get_task / abletime_create_task / abletime_ensure_task \u2014 AbleTime Account personal access token (hosted MCP). Call orientation first. If work has no task yet, abletime_ensure_task creates one to track against (or create_thread from the default branch does that automatically when AbleTime is the preferred issue source).",
|
|
51
51
|
"- list_teams / slack_list_channels / slack_list_users / slack_search / slack_read / slack_post / slack_replies \u2014 Slack workspaces from Settings \u2192 Remote; pass team_id from list_teams",
|
|
52
52
|
"- Optional connectors (Vercel, Supabase, PostHog, Sentry) in Settings \u2192 Connectors inject tokens into worktree agent env when connected. Prefer official CLIs (`vercel`, `supabase`, `sentry-cli`) with those env vars. PostHog has no first-class CLI \u2014 use the HTTP API (`POSTHOG_PERSONAL_API_KEY`). If a CLI is missing, the user can Install CLI on that row (not auto-installed on Connect). Do not add vendor MCPs or ask the user to paste tokens again. Git (`gh`) stays Settings \u2192 Git; issue tracking stays Settings \u2192 Issues; Slack stays Settings \u2192 Remote (Sideboard MCP).",
|
|
@@ -65,7 +65,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
65
65
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
66
66
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
67
67
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn). force_stop: true only to replace a wrong in-flight request \u2014 never to check in, resume after a halt notice, or because wait_for_turn returned stillRunning (that kills the child mid-thought)",
|
|
68
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
68
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). stillRunning is the source of truth \u2014 if it is false, the child is not working; do not tell the user it is running or \u201Cwaiting for a gate,\u201D even if status still says running/queued. If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. If stillRunning stays true across many waits with the same lastActivityAt, the child is stuck \u2014 tell the user; do not invent a gate. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
69
69
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
70
70
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
71
71
|
"Setup / run:",
|
|
@@ -74,7 +74,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
74
74
|
"Inspect / review / PRs:",
|
|
75
75
|
"- get_diff \u2014 compact diff summary",
|
|
76
76
|
'- request_review \u2014 open a Review chat tab on a worktree thread (attaches .claude/skills/review/SKILL.md when present, else seeds that skill / local guidelines; sends "Review changes in this workspace."); then wait_for_turn (loop while stillRunning) / get_turn_result on the returned id',
|
|
77
|
-
"- 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 (loop while stillRunning). Prefer this over paraphrasing.",
|
|
77
|
+
"- 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 (loop while stillRunning). Prefer this over paraphrasing. If ask_git / get_thread lastError says the GraphQL/PR body is too long, the branch is already pushed \u2014 send_to_thread so the worktree agent runs `gh pr create --body-file` with a short description. Do not invent SSH or auth failures from that error.",
|
|
78
78
|
'- 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.',
|
|
79
79
|
'- 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.',
|
|
80
80
|
"Process guides:",
|