@h-rig/runtime 0.0.6-alpha.2 → 0.0.6-alpha.4
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/bin/rig-agent-dispatch.js +93 -14
- package/dist/bin/rig-agent.js +83 -26
- package/dist/src/control-plane/agent-wrapper.js +93 -14
- package/dist/src/control-plane/harness-main.js +83 -26
- package/dist/src/control-plane/hooks/completion-verification.js +85 -28
- package/dist/src/control-plane/hooks/inject-context.js +2 -2
- package/dist/src/control-plane/hooks/submodule-branch.js +26 -3
- package/dist/src/control-plane/hooks/task-runtime-start.js +26 -3
- package/dist/src/control-plane/native/git-ops.js +81 -24
- package/dist/src/control-plane/native/harness-cli.js +83 -26
- package/dist/src/control-plane/native/pr-automation.js +87 -16
- package/dist/src/control-plane/native/run-ops.js +23 -6
- package/dist/src/control-plane/native/task-ops.js +2 -2
- package/dist/src/control-plane/native/validator.js +2 -2
- package/dist/src/control-plane/native/verifier.js +2 -2
- package/dist/src/control-plane/runtime/index.js +38 -9
- package/dist/src/control-plane/runtime/isolation/home.js +31 -6
- package/dist/src/control-plane/runtime/isolation/index.js +38 -9
- package/dist/src/control-plane/runtime/isolation/runner.js +31 -6
- package/dist/src/control-plane/runtime/isolation/shared.js +9 -6
- package/dist/src/control-plane/runtime/isolation.js +38 -9
- package/dist/src/control-plane/runtime/queue.js +38 -9
- package/dist/src/control-plane/tasks/source-aware-task-config-source.js +14 -2
- package/dist/src/control-plane/tasks/source-lifecycle.js +2 -2
- package/native/darwin-arm64/{bin/rig-git → rig-git} +0 -0
- package/native/darwin-arm64/rig-git.build-manifest.json +4 -0
- package/native/darwin-arm64/{bin/rig-shell → rig-shell} +0 -0
- package/native/darwin-arm64/rig-shell.build-manifest.json +4 -0
- package/native/darwin-arm64/{bin/rig-tools → rig-tools} +0 -0
- package/native/darwin-arm64/rig-tools.build-manifest.json +4 -0
- package/native/darwin-arm64/{lib/runtime-native.dylib → runtime-native.dylib} +0 -0
- package/package.json +6 -6
- package/native/darwin-arm64/lib/runtime-native-darwin-arm64.dylib +0 -0
- package/native/darwin-arm64/manifest.json +0 -1
- package/native/linux-x64/bin/rig-git +0 -0
- package/native/linux-x64/bin/rig-shell +0 -0
- package/native/linux-x64/bin/rig-tools +0 -0
- package/native/linux-x64/lib/runtime-native-linux-x64.so +0 -0
- package/native/linux-x64/lib/runtime-native.so +0 -0
- package/native/linux-x64/manifest.json +0 -1
|
@@ -1203,8 +1203,8 @@ function githubStatusFor(issue) {
|
|
|
1203
1203
|
return "open";
|
|
1204
1204
|
}
|
|
1205
1205
|
function selectedGitHubEnv() {
|
|
1206
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
1207
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
1206
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
1207
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
1208
1208
|
}
|
|
1209
1209
|
function ghSpawnOptions() {
|
|
1210
1210
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -5989,12 +5989,12 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
|
|
|
5989
5989
|
"task-result.json",
|
|
5990
5990
|
"validation-summary.json"
|
|
5991
5991
|
]);
|
|
5992
|
-
function resolveHostRigBinDir(root) {
|
|
5993
|
-
return resolve24(root, ".rig", "bin");
|
|
5994
|
-
}
|
|
5995
5992
|
function isRuntimeGatewayGitPath(candidate) {
|
|
5996
5993
|
return /\/\.rig\/bin\/git$/.test(candidate.replace(/\\/g, "/"));
|
|
5997
5994
|
}
|
|
5995
|
+
function isRuntimeGatewayGhPath(candidate) {
|
|
5996
|
+
return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
|
|
5997
|
+
}
|
|
5998
5998
|
function resolveOptionalMonorepoRoot(projectRoot) {
|
|
5999
5999
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6000
6000
|
if (runtimeWorkspace && existsSync21(resolve24(runtimeWorkspace, ".git"))) {
|
|
@@ -6029,6 +6029,9 @@ function resolveGitBinary(projectRoot) {
|
|
|
6029
6029
|
}
|
|
6030
6030
|
return "git";
|
|
6031
6031
|
}
|
|
6032
|
+
function escapeRegExp2(value) {
|
|
6033
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6034
|
+
}
|
|
6032
6035
|
function safeCurrentTaskId(projectRoot) {
|
|
6033
6036
|
try {
|
|
6034
6037
|
const taskId = currentTaskId(projectRoot);
|
|
@@ -6187,17 +6190,15 @@ function gitOpenPr(options) {
|
|
|
6187
6190
|
const target = options.target || (taskId ? "monorepo" : "project");
|
|
6188
6191
|
let repoRoot = options.projectRoot;
|
|
6189
6192
|
let repoLabel = "project-rig";
|
|
6190
|
-
|
|
6193
|
+
const envBase = target === "monorepo" ? process.env.RIG_PR_BASE_MONOREPO?.trim() || "" : process.env.RIG_PR_BASE_PROJECT?.trim() || "";
|
|
6191
6194
|
if (target === "monorepo") {
|
|
6192
6195
|
repoRoot = resolveOptionalMonorepoRoot(options.projectRoot) || resolveMonorepoRoot2(options.projectRoot);
|
|
6193
6196
|
repoLabel = "monorepo";
|
|
6194
|
-
defaultBase = process.env.RIG_PR_BASE_MONOREPO || "main";
|
|
6195
6197
|
if (taskId) {
|
|
6196
6198
|
gitSyncBranch(options.projectRoot, taskId, "monorepo");
|
|
6197
6199
|
}
|
|
6198
6200
|
} else if (taskId) {
|
|
6199
6201
|
gitSyncBranch(options.projectRoot, taskId, "project");
|
|
6200
|
-
defaultBase = inferProjectBase(options.projectRoot, defaultBase);
|
|
6201
6202
|
}
|
|
6202
6203
|
if (!existsSync21(resolve24(repoRoot, ".git"))) {
|
|
6203
6204
|
throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
|
|
@@ -6206,9 +6207,9 @@ function gitOpenPr(options) {
|
|
|
6206
6207
|
if (!branch || branch === "HEAD") {
|
|
6207
6208
|
throw new Error(`Cannot open PR from detached HEAD in ${repoLabel}. Checkout a branch first.`);
|
|
6208
6209
|
}
|
|
6209
|
-
const base = options.base || defaultBase;
|
|
6210
6210
|
const repoNameWithOwner = resolveRepoNameWithOwner(options.projectRoot, repoRoot);
|
|
6211
6211
|
const networkRemote = resolveNetworkRemoteName(options.projectRoot, repoRoot, repoNameWithOwner);
|
|
6212
|
+
const base = options.base || envBase || inferRepositoryDefaultBase(options.projectRoot, repoRoot, repoNameWithOwner, networkRemote, target === "project" ? inferProjectBase(options.projectRoot, "main") : "main");
|
|
6212
6213
|
refreshRemoteBaseRef(options.projectRoot, repoRoot, base);
|
|
6213
6214
|
let reviewer = (options.reviewer || "").trim();
|
|
6214
6215
|
let reviewerSource = reviewer ? "flag" : undefined;
|
|
@@ -6244,6 +6245,7 @@ function gitOpenPr(options) {
|
|
|
6244
6245
|
"",
|
|
6245
6246
|
"## Task",
|
|
6246
6247
|
`- beads: ${taskId || "n/a"}`,
|
|
6248
|
+
...defaultPrRunLines(taskId, repoNameWithOwner),
|
|
6247
6249
|
"",
|
|
6248
6250
|
"## Review",
|
|
6249
6251
|
"- Completion verification will run validation, verifier review, and PR policy checks.",
|
|
@@ -6335,6 +6337,29 @@ function gitOpenPr(options) {
|
|
|
6335
6337
|
}
|
|
6336
6338
|
return result;
|
|
6337
6339
|
}
|
|
6340
|
+
function defaultPrRunLines(taskId, repoNameWithOwner) {
|
|
6341
|
+
const lines = [];
|
|
6342
|
+
const runId = process.env.RIG_SERVER_RUN_ID?.trim();
|
|
6343
|
+
if (runId) {
|
|
6344
|
+
lines.push(`- Run: ${runId}`);
|
|
6345
|
+
}
|
|
6346
|
+
const closeout = defaultPrCloseoutLine(taskId, repoNameWithOwner);
|
|
6347
|
+
if (closeout) {
|
|
6348
|
+
lines.push(`- ${closeout}`);
|
|
6349
|
+
}
|
|
6350
|
+
return lines;
|
|
6351
|
+
}
|
|
6352
|
+
function defaultPrCloseoutLine(taskId, repoNameWithOwner) {
|
|
6353
|
+
const sourceIssueId = loadRuntimeContextFromEnv()?.sourceTask?.sourceIssueId;
|
|
6354
|
+
if (sourceIssueId) {
|
|
6355
|
+
const match = sourceIssueId.match(/^([^#]+)#(\d+)$/);
|
|
6356
|
+
if (match) {
|
|
6357
|
+
const [, sourceRepo, issueNumber] = match;
|
|
6358
|
+
return sourceRepo.toLowerCase() === repoNameWithOwner.toLowerCase() ? `Closes #${issueNumber}` : `Closes ${sourceRepo}#${issueNumber}`;
|
|
6359
|
+
}
|
|
6360
|
+
}
|
|
6361
|
+
return /^\d+$/.test(taskId) ? `Closes #${taskId}` : "";
|
|
6362
|
+
}
|
|
6338
6363
|
function readPrViewState(gh, repoRoot, repoNameWithOwner, prUrl) {
|
|
6339
6364
|
const view = runCapture2(withGhRepo([
|
|
6340
6365
|
gh,
|
|
@@ -6485,32 +6510,19 @@ function resolveGithubCliBinary(projectRoot) {
|
|
|
6485
6510
|
if (explicit) {
|
|
6486
6511
|
candidates.add(explicit);
|
|
6487
6512
|
}
|
|
6513
|
+
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
6514
|
+
candidates.add(candidate);
|
|
6515
|
+
}
|
|
6488
6516
|
const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
|
|
6489
6517
|
for (const entry of explicitPathEntries) {
|
|
6490
6518
|
candidates.add(resolve24(entry, "gh"));
|
|
6491
6519
|
}
|
|
6492
|
-
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
6493
|
-
if (hostProjectRoot) {
|
|
6494
|
-
candidates.add(resolve24(resolveHostRigBinDir(hostProjectRoot), "gh"));
|
|
6495
|
-
}
|
|
6496
|
-
candidates.add(resolve24(resolveHostRigBinDir(projectRoot), "gh"));
|
|
6497
|
-
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6498
|
-
if (runtimeContext?.binDir) {
|
|
6499
|
-
candidates.add(resolve24(runtimeContext.binDir, "gh"));
|
|
6500
|
-
}
|
|
6501
|
-
const runtimeHome = process.env.RIG_RUNTIME_HOME?.trim();
|
|
6502
|
-
if (runtimeHome) {
|
|
6503
|
-
candidates.add(resolve24(runtimeHome, "bin", "gh"));
|
|
6504
|
-
}
|
|
6505
|
-
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
|
|
6506
|
-
candidates.add(candidate);
|
|
6507
|
-
}
|
|
6508
6520
|
const bunResolved = Bun.which("gh");
|
|
6509
6521
|
if (bunResolved) {
|
|
6510
6522
|
candidates.add(bunResolved);
|
|
6511
6523
|
}
|
|
6512
6524
|
for (const candidate of candidates) {
|
|
6513
|
-
if (candidate && existsSync21(candidate)) {
|
|
6525
|
+
if (candidate && existsSync21(candidate) && !isRuntimeGatewayGhPath(candidate)) {
|
|
6514
6526
|
return candidate;
|
|
6515
6527
|
}
|
|
6516
6528
|
}
|
|
@@ -6659,6 +6671,32 @@ function withGhRepo(command, repoNameWithOwner) {
|
|
|
6659
6671
|
}
|
|
6660
6672
|
return [command[0], command[1], command[2], ...ghRepoArgs(repoNameWithOwner), ...command.slice(3)];
|
|
6661
6673
|
}
|
|
6674
|
+
function inferRepositoryDefaultBase(projectRoot, repoRoot, repoNameWithOwner, remoteName, fallback) {
|
|
6675
|
+
const remote = remoteName || "origin";
|
|
6676
|
+
const symbolic = runCapture2(gitCmd(projectRoot, repoRoot, "symbolic-ref", "--short", `refs/remotes/${remote}/HEAD`), projectRoot);
|
|
6677
|
+
if (symbolic.exitCode === 0) {
|
|
6678
|
+
const ref = symbolic.stdout.trim().replace(new RegExp(`^${escapeRegExp2(remote)}/`), "");
|
|
6679
|
+
if (ref && ref !== "HEAD") {
|
|
6680
|
+
return ref;
|
|
6681
|
+
}
|
|
6682
|
+
}
|
|
6683
|
+
const lsRemote = runCapture2(gitCmd(projectRoot, repoRoot, "ls-remote", "--symref", remote, "HEAD"), projectRoot);
|
|
6684
|
+
if (lsRemote.exitCode === 0) {
|
|
6685
|
+
const match = lsRemote.stdout.match(/^ref:\s+refs\/heads\/([^\t\r\n]+)\s+HEAD/m);
|
|
6686
|
+
if (match?.[1]) {
|
|
6687
|
+
return match[1];
|
|
6688
|
+
}
|
|
6689
|
+
}
|
|
6690
|
+
const gh = resolveGithubCliBinary(projectRoot);
|
|
6691
|
+
if (gh && repoNameWithOwner) {
|
|
6692
|
+
const api = runCapture2(withGhRepo([gh, "repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"], repoNameWithOwner), repoRoot);
|
|
6693
|
+
const branch = api.exitCode === 0 ? api.stdout.trim() : "";
|
|
6694
|
+
if (branch) {
|
|
6695
|
+
return branch;
|
|
6696
|
+
}
|
|
6697
|
+
}
|
|
6698
|
+
return fallback;
|
|
6699
|
+
}
|
|
6662
6700
|
function inferProjectBase(projectRoot, fallback) {
|
|
6663
6701
|
const containing = runCapture2(gitCmd(projectRoot, projectRoot, "branch", "-r", "--contains", "HEAD"), projectRoot);
|
|
6664
6702
|
if (containing.exitCode !== 0) {
|
|
@@ -7040,6 +7078,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7040
7078
|
}
|
|
7041
7079
|
env[key] = value;
|
|
7042
7080
|
}
|
|
7081
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
7082
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
7083
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
7084
|
+
}
|
|
7043
7085
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
7044
7086
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
7045
7087
|
}
|
|
@@ -7063,6 +7105,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7063
7105
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
7064
7106
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
7065
7107
|
}
|
|
7108
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
7109
|
+
if (gitHubToken) {
|
|
7110
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
7111
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
7112
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
7113
|
+
applyGitHubCredentialHelperEnv(env);
|
|
7114
|
+
}
|
|
7066
7115
|
if (runtimeKnownHosts && existsSync21(runtimeKnownHosts)) {
|
|
7067
7116
|
const sshParts = [
|
|
7068
7117
|
"ssh",
|
|
@@ -7079,6 +7128,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7079
7128
|
}
|
|
7080
7129
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
7081
7130
|
}
|
|
7131
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
7132
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
7133
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
7134
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
7135
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
7136
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
7137
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
7138
|
+
}
|
|
7082
7139
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
7083
7140
|
if (!runtimeRoot) {
|
|
7084
7141
|
return {};
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import { appendFileSync as appendFileSync2, existsSync as existsSync21, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync11 } from "fs";
|
|
6
6
|
import { resolve as resolve24 } from "path";
|
|
7
7
|
import {
|
|
8
|
-
escapeRegExp,
|
|
8
|
+
escapeRegExp as escapeRegExp2,
|
|
9
9
|
resolveBunCli,
|
|
10
10
|
resolveBunCliInvocation,
|
|
11
11
|
resolveProjectRoot,
|
|
@@ -2645,8 +2645,8 @@ function ensureStatusLabel(bin, repo, spawnFn, label) {
|
|
|
2645
2645
|
}
|
|
2646
2646
|
}
|
|
2647
2647
|
function selectedGitHubEnv() {
|
|
2648
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
2649
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
2648
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
2649
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
2650
2650
|
}
|
|
2651
2651
|
function ghSpawnOptions() {
|
|
2652
2652
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -5993,12 +5993,12 @@ var TASK_ARTIFACT_STAGE_FALLBACK = new Set([
|
|
|
5993
5993
|
"task-result.json",
|
|
5994
5994
|
"validation-summary.json"
|
|
5995
5995
|
]);
|
|
5996
|
-
function resolveHostRigBinDir(root) {
|
|
5997
|
-
return resolve23(root, ".rig", "bin");
|
|
5998
|
-
}
|
|
5999
5996
|
function isRuntimeGatewayGitPath(candidate) {
|
|
6000
5997
|
return /\/\.rig\/bin\/git$/.test(candidate.replace(/\\/g, "/"));
|
|
6001
5998
|
}
|
|
5999
|
+
function isRuntimeGatewayGhPath(candidate) {
|
|
6000
|
+
return /\/\.rig\/bin\/gh$/.test(candidate.replace(/\\/g, "/"));
|
|
6001
|
+
}
|
|
6002
6002
|
function resolveOptionalMonorepoRoot(projectRoot) {
|
|
6003
6003
|
const runtimeWorkspace = process.env.RIG_TASK_WORKSPACE?.trim();
|
|
6004
6004
|
if (runtimeWorkspace && existsSync20(resolve23(runtimeWorkspace, ".git"))) {
|
|
@@ -6033,6 +6033,9 @@ function resolveGitBinary(projectRoot) {
|
|
|
6033
6033
|
}
|
|
6034
6034
|
return "git";
|
|
6035
6035
|
}
|
|
6036
|
+
function escapeRegExp(value) {
|
|
6037
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
6038
|
+
}
|
|
6036
6039
|
function safeCurrentTaskId(projectRoot) {
|
|
6037
6040
|
try {
|
|
6038
6041
|
const taskId = currentTaskId(projectRoot);
|
|
@@ -6101,17 +6104,15 @@ function gitOpenPr(options) {
|
|
|
6101
6104
|
const target = options.target || (taskId ? "monorepo" : "project");
|
|
6102
6105
|
let repoRoot = options.projectRoot;
|
|
6103
6106
|
let repoLabel = "project-rig";
|
|
6104
|
-
|
|
6107
|
+
const envBase = target === "monorepo" ? process.env.RIG_PR_BASE_MONOREPO?.trim() || "" : process.env.RIG_PR_BASE_PROJECT?.trim() || "";
|
|
6105
6108
|
if (target === "monorepo") {
|
|
6106
6109
|
repoRoot = resolveOptionalMonorepoRoot(options.projectRoot) || resolveMonorepoRoot2(options.projectRoot);
|
|
6107
6110
|
repoLabel = "monorepo";
|
|
6108
|
-
defaultBase = process.env.RIG_PR_BASE_MONOREPO || "main";
|
|
6109
6111
|
if (taskId) {
|
|
6110
6112
|
gitSyncBranch(options.projectRoot, taskId, "monorepo");
|
|
6111
6113
|
}
|
|
6112
6114
|
} else if (taskId) {
|
|
6113
6115
|
gitSyncBranch(options.projectRoot, taskId, "project");
|
|
6114
|
-
defaultBase = inferProjectBase(options.projectRoot, defaultBase);
|
|
6115
6116
|
}
|
|
6116
6117
|
if (!existsSync20(resolve23(repoRoot, ".git"))) {
|
|
6117
6118
|
throw new Error(`Repository not available for open-pr target ${target}: ${repoRoot}`);
|
|
@@ -6120,9 +6121,9 @@ function gitOpenPr(options) {
|
|
|
6120
6121
|
if (!branch || branch === "HEAD") {
|
|
6121
6122
|
throw new Error(`Cannot open PR from detached HEAD in ${repoLabel}. Checkout a branch first.`);
|
|
6122
6123
|
}
|
|
6123
|
-
const base = options.base || defaultBase;
|
|
6124
6124
|
const repoNameWithOwner = resolveRepoNameWithOwner(options.projectRoot, repoRoot);
|
|
6125
6125
|
const networkRemote = resolveNetworkRemoteName(options.projectRoot, repoRoot, repoNameWithOwner);
|
|
6126
|
+
const base = options.base || envBase || inferRepositoryDefaultBase(options.projectRoot, repoRoot, repoNameWithOwner, networkRemote, target === "project" ? inferProjectBase(options.projectRoot, "main") : "main");
|
|
6126
6127
|
refreshRemoteBaseRef(options.projectRoot, repoRoot, base);
|
|
6127
6128
|
let reviewer = (options.reviewer || "").trim();
|
|
6128
6129
|
let reviewerSource = reviewer ? "flag" : undefined;
|
|
@@ -6158,6 +6159,7 @@ function gitOpenPr(options) {
|
|
|
6158
6159
|
"",
|
|
6159
6160
|
"## Task",
|
|
6160
6161
|
`- beads: ${taskId || "n/a"}`,
|
|
6162
|
+
...defaultPrRunLines(taskId, repoNameWithOwner),
|
|
6161
6163
|
"",
|
|
6162
6164
|
"## Review",
|
|
6163
6165
|
"- Completion verification will run validation, verifier review, and PR policy checks.",
|
|
@@ -6249,6 +6251,29 @@ function gitOpenPr(options) {
|
|
|
6249
6251
|
}
|
|
6250
6252
|
return result;
|
|
6251
6253
|
}
|
|
6254
|
+
function defaultPrRunLines(taskId, repoNameWithOwner) {
|
|
6255
|
+
const lines = [];
|
|
6256
|
+
const runId = process.env.RIG_SERVER_RUN_ID?.trim();
|
|
6257
|
+
if (runId) {
|
|
6258
|
+
lines.push(`- Run: ${runId}`);
|
|
6259
|
+
}
|
|
6260
|
+
const closeout = defaultPrCloseoutLine(taskId, repoNameWithOwner);
|
|
6261
|
+
if (closeout) {
|
|
6262
|
+
lines.push(`- ${closeout}`);
|
|
6263
|
+
}
|
|
6264
|
+
return lines;
|
|
6265
|
+
}
|
|
6266
|
+
function defaultPrCloseoutLine(taskId, repoNameWithOwner) {
|
|
6267
|
+
const sourceIssueId = loadRuntimeContextFromEnv()?.sourceTask?.sourceIssueId;
|
|
6268
|
+
if (sourceIssueId) {
|
|
6269
|
+
const match = sourceIssueId.match(/^([^#]+)#(\d+)$/);
|
|
6270
|
+
if (match) {
|
|
6271
|
+
const [, sourceRepo, issueNumber] = match;
|
|
6272
|
+
return sourceRepo.toLowerCase() === repoNameWithOwner.toLowerCase() ? `Closes #${issueNumber}` : `Closes ${sourceRepo}#${issueNumber}`;
|
|
6273
|
+
}
|
|
6274
|
+
}
|
|
6275
|
+
return /^\d+$/.test(taskId) ? `Closes #${taskId}` : "";
|
|
6276
|
+
}
|
|
6252
6277
|
function resolveTaskBranchRef(projectRoot, taskId) {
|
|
6253
6278
|
return `rig/${resolveTaskBranchId(projectRoot, taskId)}`;
|
|
6254
6279
|
}
|
|
@@ -6495,32 +6520,19 @@ function resolveGithubCliBinary(projectRoot) {
|
|
|
6495
6520
|
if (explicit) {
|
|
6496
6521
|
candidates.add(explicit);
|
|
6497
6522
|
}
|
|
6523
|
+
for (const candidate of ["/usr/bin/gh", "/opt/homebrew/bin/gh", "/usr/local/bin/gh"]) {
|
|
6524
|
+
candidates.add(candidate);
|
|
6525
|
+
}
|
|
6498
6526
|
const explicitPathEntries = (process.env.PATH || "").split(":").map((entry) => entry.trim()).filter(Boolean);
|
|
6499
6527
|
for (const entry of explicitPathEntries) {
|
|
6500
6528
|
candidates.add(resolve23(entry, "gh"));
|
|
6501
6529
|
}
|
|
6502
|
-
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim();
|
|
6503
|
-
if (hostProjectRoot) {
|
|
6504
|
-
candidates.add(resolve23(resolveHostRigBinDir(hostProjectRoot), "gh"));
|
|
6505
|
-
}
|
|
6506
|
-
candidates.add(resolve23(resolveHostRigBinDir(projectRoot), "gh"));
|
|
6507
|
-
const runtimeContext = loadRuntimeContextFromEnv();
|
|
6508
|
-
if (runtimeContext?.binDir) {
|
|
6509
|
-
candidates.add(resolve23(runtimeContext.binDir, "gh"));
|
|
6510
|
-
}
|
|
6511
|
-
const runtimeHome = process.env.RIG_RUNTIME_HOME?.trim();
|
|
6512
|
-
if (runtimeHome) {
|
|
6513
|
-
candidates.add(resolve23(runtimeHome, "bin", "gh"));
|
|
6514
|
-
}
|
|
6515
|
-
for (const candidate of ["/opt/homebrew/bin/gh", "/usr/local/bin/gh", "/usr/bin/gh"]) {
|
|
6516
|
-
candidates.add(candidate);
|
|
6517
|
-
}
|
|
6518
6530
|
const bunResolved = Bun.which("gh");
|
|
6519
6531
|
if (bunResolved) {
|
|
6520
6532
|
candidates.add(bunResolved);
|
|
6521
6533
|
}
|
|
6522
6534
|
for (const candidate of candidates) {
|
|
6523
|
-
if (candidate && existsSync20(candidate)) {
|
|
6535
|
+
if (candidate && existsSync20(candidate) && !isRuntimeGatewayGhPath(candidate)) {
|
|
6524
6536
|
return candidate;
|
|
6525
6537
|
}
|
|
6526
6538
|
}
|
|
@@ -6669,6 +6681,32 @@ function withGhRepo(command, repoNameWithOwner) {
|
|
|
6669
6681
|
}
|
|
6670
6682
|
return [command[0], command[1], command[2], ...ghRepoArgs(repoNameWithOwner), ...command.slice(3)];
|
|
6671
6683
|
}
|
|
6684
|
+
function inferRepositoryDefaultBase(projectRoot, repoRoot, repoNameWithOwner, remoteName, fallback) {
|
|
6685
|
+
const remote = remoteName || "origin";
|
|
6686
|
+
const symbolic = runCapture2(gitCmd(projectRoot, repoRoot, "symbolic-ref", "--short", `refs/remotes/${remote}/HEAD`), projectRoot);
|
|
6687
|
+
if (symbolic.exitCode === 0) {
|
|
6688
|
+
const ref = symbolic.stdout.trim().replace(new RegExp(`^${escapeRegExp(remote)}/`), "");
|
|
6689
|
+
if (ref && ref !== "HEAD") {
|
|
6690
|
+
return ref;
|
|
6691
|
+
}
|
|
6692
|
+
}
|
|
6693
|
+
const lsRemote = runCapture2(gitCmd(projectRoot, repoRoot, "ls-remote", "--symref", remote, "HEAD"), projectRoot);
|
|
6694
|
+
if (lsRemote.exitCode === 0) {
|
|
6695
|
+
const match = lsRemote.stdout.match(/^ref:\s+refs\/heads\/([^\t\r\n]+)\s+HEAD/m);
|
|
6696
|
+
if (match?.[1]) {
|
|
6697
|
+
return match[1];
|
|
6698
|
+
}
|
|
6699
|
+
}
|
|
6700
|
+
const gh = resolveGithubCliBinary(projectRoot);
|
|
6701
|
+
if (gh && repoNameWithOwner) {
|
|
6702
|
+
const api = runCapture2(withGhRepo([gh, "repo", "view", "--json", "defaultBranchRef", "--jq", ".defaultBranchRef.name"], repoNameWithOwner), repoRoot);
|
|
6703
|
+
const branch = api.exitCode === 0 ? api.stdout.trim() : "";
|
|
6704
|
+
if (branch) {
|
|
6705
|
+
return branch;
|
|
6706
|
+
}
|
|
6707
|
+
}
|
|
6708
|
+
return fallback;
|
|
6709
|
+
}
|
|
6672
6710
|
function inferProjectBase(projectRoot, fallback) {
|
|
6673
6711
|
const containing = runCapture2(gitCmd(projectRoot, projectRoot, "branch", "-r", "--contains", "HEAD"), projectRoot);
|
|
6674
6712
|
if (containing.exitCode !== 0) {
|
|
@@ -7013,6 +7051,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7013
7051
|
}
|
|
7014
7052
|
env[key] = value;
|
|
7015
7053
|
}
|
|
7054
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
7055
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
7056
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
7057
|
+
}
|
|
7016
7058
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
7017
7059
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
7018
7060
|
}
|
|
@@ -7036,6 +7078,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7036
7078
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
7037
7079
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
7038
7080
|
}
|
|
7081
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
7082
|
+
if (gitHubToken) {
|
|
7083
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
7084
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
7085
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
7086
|
+
applyGitHubCredentialHelperEnv(env);
|
|
7087
|
+
}
|
|
7039
7088
|
if (runtimeKnownHosts && existsSync20(runtimeKnownHosts)) {
|
|
7040
7089
|
const sshParts = [
|
|
7041
7090
|
"ssh",
|
|
@@ -7052,6 +7101,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
7052
7101
|
}
|
|
7053
7102
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
7054
7103
|
}
|
|
7104
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
7105
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
7106
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
7107
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
7108
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
7109
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
7110
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
7111
|
+
}
|
|
7055
7112
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
7056
7113
|
if (!runtimeRoot) {
|
|
7057
7114
|
return {};
|
|
@@ -7493,7 +7550,7 @@ async function recordVerifierFailure(projectRoot, taskId, paths) {
|
|
|
7493
7550
|
let attempts = 1;
|
|
7494
7551
|
if (existsSync21(failedApproachesPath)) {
|
|
7495
7552
|
const content = readFileSync12(failedApproachesPath, "utf-8");
|
|
7496
|
-
attempts = (content.match(new RegExp(`^## ${
|
|
7553
|
+
attempts = (content.match(new RegExp(`^## ${escapeRegExp2(taskId)}\\b`, "gm")) || []).length + 1;
|
|
7497
7554
|
} else {
|
|
7498
7555
|
mkdirSync11(resolve24(failedApproachesPath, ".."), { recursive: true });
|
|
7499
7556
|
writeFileSync11(failedApproachesPath, `# Failed Approaches
|
|
@@ -2484,8 +2484,8 @@ function githubStatusFor(issue) {
|
|
|
2484
2484
|
return "open";
|
|
2485
2485
|
}
|
|
2486
2486
|
function selectedGitHubEnv() {
|
|
2487
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
2488
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
2487
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
2488
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
2489
2489
|
}
|
|
2490
2490
|
function ghSpawnOptions() {
|
|
2491
2491
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -1706,8 +1706,8 @@ function githubStatusFor(issue) {
|
|
|
1706
1706
|
return "open";
|
|
1707
1707
|
}
|
|
1708
1708
|
function selectedGitHubEnv() {
|
|
1709
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
1710
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
1709
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
1710
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
1711
1711
|
}
|
|
1712
1712
|
function ghSpawnOptions() {
|
|
1713
1713
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -4509,6 +4509,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4509
4509
|
}
|
|
4510
4510
|
env[key] = value;
|
|
4511
4511
|
}
|
|
4512
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
4513
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
4514
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
4515
|
+
}
|
|
4512
4516
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
4513
4517
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
4514
4518
|
}
|
|
@@ -4532,6 +4536,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4532
4536
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
4533
4537
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
4534
4538
|
}
|
|
4539
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
4540
|
+
if (gitHubToken) {
|
|
4541
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
4542
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
4543
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
4544
|
+
applyGitHubCredentialHelperEnv(env);
|
|
4545
|
+
}
|
|
4535
4546
|
if (runtimeKnownHosts && existsSync22(runtimeKnownHosts)) {
|
|
4536
4547
|
const sshParts = [
|
|
4537
4548
|
"ssh",
|
|
@@ -4548,6 +4559,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4548
4559
|
}
|
|
4549
4560
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
4550
4561
|
}
|
|
4562
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
4563
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
4564
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
4565
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
4566
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
4567
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
4568
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
4569
|
+
}
|
|
4551
4570
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
4552
4571
|
if (!runtimeRoot) {
|
|
4553
4572
|
return {};
|
|
@@ -7603,7 +7622,11 @@ async function ensureAgentRuntime(options) {
|
|
|
7603
7622
|
mkdirSync21(runtime.binDir, { recursive: true });
|
|
7604
7623
|
mkdirSync21(workspaceLayout.distDir, { recursive: true });
|
|
7605
7624
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
7606
|
-
|
|
7625
|
+
if (options.preserveTaskArtifacts) {
|
|
7626
|
+
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
7627
|
+
} else {
|
|
7628
|
+
await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
|
|
7629
|
+
}
|
|
7607
7630
|
const ctx = {
|
|
7608
7631
|
runtimeId: options.id,
|
|
7609
7632
|
taskId: options.taskId,
|
|
@@ -1706,8 +1706,8 @@ function githubStatusFor(issue) {
|
|
|
1706
1706
|
return "open";
|
|
1707
1707
|
}
|
|
1708
1708
|
function selectedGitHubEnv() {
|
|
1709
|
-
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim()
|
|
1710
|
-
return { GH_TOKEN: token, GITHUB_TOKEN: token };
|
|
1709
|
+
const token = process.env.RIG_GITHUB_SELECTED_TOKEN?.trim() || process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
1710
|
+
return { GH_TOKEN: token, GITHUB_TOKEN: token, RIG_GITHUB_TOKEN: token };
|
|
1711
1711
|
}
|
|
1712
1712
|
function ghSpawnOptions() {
|
|
1713
1713
|
return { encoding: "utf-8", env: { ...process.env, ...selectedGitHubEnv() } };
|
|
@@ -4509,6 +4509,10 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4509
4509
|
}
|
|
4510
4510
|
env[key] = value;
|
|
4511
4511
|
}
|
|
4512
|
+
const rigGithubToken = process.env.RIG_GITHUB_TOKEN?.trim() || "";
|
|
4513
|
+
if (rigGithubToken && !env.GITHUB_TOKEN && !env.GH_TOKEN) {
|
|
4514
|
+
env.GITHUB_TOKEN = rigGithubToken;
|
|
4515
|
+
}
|
|
4512
4516
|
if (!env.GITHUB_TOKEN && env.GH_TOKEN) {
|
|
4513
4517
|
env.GITHUB_TOKEN = env.GH_TOKEN;
|
|
4514
4518
|
}
|
|
@@ -4532,6 +4536,13 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4532
4536
|
if (!env.GH_TOKEN && env.GITHUB_TOKEN) {
|
|
4533
4537
|
env.GH_TOKEN = env.GITHUB_TOKEN;
|
|
4534
4538
|
}
|
|
4539
|
+
const gitHubToken = env.GITHUB_TOKEN || env.GH_TOKEN || env.RIG_GITHUB_TOKEN || rigGithubToken;
|
|
4540
|
+
if (gitHubToken) {
|
|
4541
|
+
env.RIG_GITHUB_TOKEN = gitHubToken;
|
|
4542
|
+
env.GITHUB_TOKEN = env.GITHUB_TOKEN || gitHubToken;
|
|
4543
|
+
env.GH_TOKEN = env.GH_TOKEN || gitHubToken;
|
|
4544
|
+
applyGitHubCredentialHelperEnv(env);
|
|
4545
|
+
}
|
|
4535
4546
|
if (runtimeKnownHosts && existsSync22(runtimeKnownHosts)) {
|
|
4536
4547
|
const sshParts = [
|
|
4537
4548
|
"ssh",
|
|
@@ -4548,6 +4559,14 @@ function runtimeGitEnv(projectRoot) {
|
|
|
4548
4559
|
}
|
|
4549
4560
|
return Object.keys(env).length > 0 ? env : undefined;
|
|
4550
4561
|
}
|
|
4562
|
+
function applyGitHubCredentialHelperEnv(env) {
|
|
4563
|
+
env.GIT_TERMINAL_PROMPT = "0";
|
|
4564
|
+
env.GIT_CONFIG_COUNT = "2";
|
|
4565
|
+
env.GIT_CONFIG_KEY_0 = "credential.helper";
|
|
4566
|
+
env.GIT_CONFIG_VALUE_0 = "";
|
|
4567
|
+
env.GIT_CONFIG_KEY_1 = "credential.helper";
|
|
4568
|
+
env.GIT_CONFIG_VALUE_1 = '!f() { test "$1" = get || exit 0; token="${GITHUB_TOKEN:-${GH_TOKEN:-${RIG_GITHUB_TOKEN:-}}}"; test -n "$token" || exit 0; echo username=x-access-token; echo password="$token"; }; f';
|
|
4569
|
+
}
|
|
4551
4570
|
function loadPersistedRuntimeSecrets(runtimeRoot) {
|
|
4552
4571
|
if (!runtimeRoot) {
|
|
4553
4572
|
return {};
|
|
@@ -7603,7 +7622,11 @@ async function ensureAgentRuntime(options) {
|
|
|
7603
7622
|
mkdirSync21(runtime.binDir, { recursive: true });
|
|
7604
7623
|
mkdirSync21(workspaceLayout.distDir, { recursive: true });
|
|
7605
7624
|
prepareRuntimeWorkspace(options.projectRoot, workspaceDir);
|
|
7606
|
-
|
|
7625
|
+
if (options.preserveTaskArtifacts) {
|
|
7626
|
+
console.log(`[rig-agent] Preserving runtime task artifacts for resume of ${options.taskId}.`);
|
|
7627
|
+
} else {
|
|
7628
|
+
await resetEphemeralTaskArtifacts(workspaceDir, options.taskId);
|
|
7629
|
+
}
|
|
7607
7630
|
const ctx = {
|
|
7608
7631
|
runtimeId: options.id,
|
|
7609
7632
|
taskId: options.taskId,
|