@h-rig/cli 0.0.6-alpha.1 → 0.0.6-alpha.3
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.js +356 -205
- package/dist/src/commands/_doctor-checks.js +31 -13
- package/dist/src/commands/_operator-view.js +20 -2
- package/dist/src/commands/_preflight.js +25 -7
- package/dist/src/commands/_server-client.js +22 -4
- package/dist/src/commands/_snapshot-upload.js +26 -8
- package/dist/src/commands/doctor.js +31 -13
- package/dist/src/commands/github.js +21 -3
- package/dist/src/commands/init.js +142 -62
- package/dist/src/commands/run.js +26 -8
- package/dist/src/commands/server.js +20 -2
- package/dist/src/commands/setup.js +36 -18
- package/dist/src/commands/task-run-driver.js +77 -5
- package/dist/src/commands/task.js +28 -10
- package/dist/src/commands.js +349 -198
- package/dist/src/index.js +356 -205
- package/package.json +4 -4
package/dist/src/index.js
CHANGED
|
@@ -2667,6 +2667,8 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
2667
2667
|
|
|
2668
2668
|
// packages/cli/src/commands/_server-client.ts
|
|
2669
2669
|
import { spawnSync } from "child_process";
|
|
2670
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
2671
|
+
import { resolve as resolve9 } from "path";
|
|
2670
2672
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
2671
2673
|
var cachedGitHubBearerToken;
|
|
2672
2674
|
function cleanToken(value) {
|
|
@@ -2676,9 +2678,25 @@ function cleanToken(value) {
|
|
|
2676
2678
|
function setGitHubBearerTokenForCurrentProcess(token) {
|
|
2677
2679
|
cachedGitHubBearerToken = cleanToken(token ?? undefined);
|
|
2678
2680
|
}
|
|
2679
|
-
function
|
|
2681
|
+
function readPrivateRemoteSessionToken(projectRoot) {
|
|
2682
|
+
const path = resolve9(projectRoot, ".rig", "state", "github-auth.json");
|
|
2683
|
+
if (!existsSync5(path))
|
|
2684
|
+
return null;
|
|
2685
|
+
try {
|
|
2686
|
+
const parsed = JSON.parse(readFileSync3(path, "utf8"));
|
|
2687
|
+
return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
|
|
2688
|
+
} catch {
|
|
2689
|
+
return null;
|
|
2690
|
+
}
|
|
2691
|
+
}
|
|
2692
|
+
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
2680
2693
|
if (cachedGitHubBearerToken !== undefined)
|
|
2681
2694
|
return cachedGitHubBearerToken;
|
|
2695
|
+
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
2696
|
+
if (privateSession) {
|
|
2697
|
+
cachedGitHubBearerToken = privateSession;
|
|
2698
|
+
return cachedGitHubBearerToken;
|
|
2699
|
+
}
|
|
2682
2700
|
const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
|
|
2683
2701
|
if (envToken) {
|
|
2684
2702
|
cachedGitHubBearerToken = envToken;
|
|
@@ -2698,7 +2716,7 @@ async function ensureServerForCli(projectRoot) {
|
|
|
2698
2716
|
if (selected?.connection.kind === "remote") {
|
|
2699
2717
|
return {
|
|
2700
2718
|
baseUrl: selected.connection.baseUrl,
|
|
2701
|
-
authToken: readGitHubBearerTokenForRemote(),
|
|
2719
|
+
authToken: readGitHubBearerTokenForRemote(projectRoot),
|
|
2702
2720
|
connectionKind: "remote"
|
|
2703
2721
|
};
|
|
2704
2722
|
}
|
|
@@ -2805,7 +2823,7 @@ async function postGitHubTokenViaServer(context, token, options = {}) {
|
|
|
2805
2823
|
const payload = await requestServerJson(context, "/api/github/auth/token", {
|
|
2806
2824
|
method: "POST",
|
|
2807
2825
|
headers: { "content-type": "application/json" },
|
|
2808
|
-
body: JSON.stringify({ token, selectedRepo: options.selectedRepo })
|
|
2826
|
+
body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot })
|
|
2809
2827
|
});
|
|
2810
2828
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
2811
2829
|
}
|
|
@@ -2826,7 +2844,7 @@ async function registerProjectViaServer(context, input) {
|
|
|
2826
2844
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
2827
2845
|
}
|
|
2828
2846
|
function sleep(ms) {
|
|
2829
|
-
return new Promise((
|
|
2847
|
+
return new Promise((resolve10) => setTimeout(resolve10, ms));
|
|
2830
2848
|
}
|
|
2831
2849
|
async function switchServerProjectRootViaServer(context, projectRoot, options = {}) {
|
|
2832
2850
|
const switched = await requestServerJson(context, "/api/server/project-root", {
|
|
@@ -2917,9 +2935,9 @@ async function submitTaskRunViaServer(context, input) {
|
|
|
2917
2935
|
}
|
|
2918
2936
|
|
|
2919
2937
|
// packages/cli/src/commands/_pi-install.ts
|
|
2920
|
-
import { existsSync as
|
|
2938
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, rmSync as rmSync3 } from "fs";
|
|
2921
2939
|
import { homedir as homedir3 } from "os";
|
|
2922
|
-
import { resolve as
|
|
2940
|
+
import { resolve as resolve10 } from "path";
|
|
2923
2941
|
var PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
2924
2942
|
var LEGACY_PI_RIG_MARKER = `// Managed by Rig. Source package: @rig/pi-rig.
|
|
2925
2943
|
export { default } from '@rig/pi-rig';
|
|
@@ -2934,11 +2952,11 @@ async function defaultCommandRunner(command, options = {}) {
|
|
|
2934
2952
|
return { exitCode, stdout, stderr };
|
|
2935
2953
|
}
|
|
2936
2954
|
function resolvePiRigExtensionPath(homeDir) {
|
|
2937
|
-
return
|
|
2955
|
+
return resolve10(homeDir, ".pi", "agent", "extensions", "pi-rig");
|
|
2938
2956
|
}
|
|
2939
|
-
function resolvePiRigPackageSource(projectRoot, exists =
|
|
2940
|
-
const localPackage =
|
|
2941
|
-
if (exists(
|
|
2957
|
+
function resolvePiRigPackageSource(projectRoot, exists = existsSync6) {
|
|
2958
|
+
const localPackage = resolve10(projectRoot, "packages", "pi-rig");
|
|
2959
|
+
if (exists(resolve10(localPackage, "package.json")))
|
|
2942
2960
|
return localPackage;
|
|
2943
2961
|
return `npm:${PI_RIG_PACKAGE_NAME}`;
|
|
2944
2962
|
}
|
|
@@ -2989,13 +3007,13 @@ async function ensurePiBinaryAvailable(input) {
|
|
|
2989
3007
|
...next.exitCode === 0 ? {} : { error: (next.stderr || next.stdout).trim() || "pi --version failed after install" }
|
|
2990
3008
|
};
|
|
2991
3009
|
}
|
|
2992
|
-
function removeManagedLegacyPiRigBridge(homeDir, exists =
|
|
3010
|
+
function removeManagedLegacyPiRigBridge(homeDir, exists = existsSync6) {
|
|
2993
3011
|
const extensionPath = resolvePiRigExtensionPath(homeDir);
|
|
2994
|
-
const indexPath =
|
|
3012
|
+
const indexPath = resolve10(extensionPath, "index.ts");
|
|
2995
3013
|
if (!exists(indexPath))
|
|
2996
3014
|
return;
|
|
2997
3015
|
try {
|
|
2998
|
-
const content =
|
|
3016
|
+
const content = readFileSync4(indexPath, "utf8");
|
|
2999
3017
|
if (content === LEGACY_PI_RIG_MARKER || content.includes("Managed by Rig. Source package: @rig/pi-rig")) {
|
|
3000
3018
|
rmSync3(extensionPath, { recursive: true, force: true });
|
|
3001
3019
|
}
|
|
@@ -3011,13 +3029,13 @@ async function checkPiRigInstall(input = {}) {
|
|
|
3011
3029
|
piRig: { ok: true, label: "pi-rig global extension", detail: extensionPath }
|
|
3012
3030
|
};
|
|
3013
3031
|
}
|
|
3014
|
-
const exists = input.exists ??
|
|
3032
|
+
const exists = input.exists ?? existsSync6;
|
|
3015
3033
|
const runner = input.commandRunner ?? defaultCommandRunner;
|
|
3016
3034
|
const piResult = await safeRun(runner, ["pi", "--version"]);
|
|
3017
3035
|
const piListResult = piResult.exitCode === 0 ? await safeRun(runner, ["pi", "list"]) : { exitCode: 1, stdout: "", stderr: "" };
|
|
3018
3036
|
const listedPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
|
|
3019
3037
|
${piListResult.stderr}`);
|
|
3020
|
-
const legacyBridge = exists(
|
|
3038
|
+
const legacyBridge = exists(resolve10(extensionPath, "index.ts"));
|
|
3021
3039
|
const hasPiRig = listedPiRig;
|
|
3022
3040
|
return {
|
|
3023
3041
|
extensionPath,
|
|
@@ -3355,7 +3373,7 @@ async function executeQueue(context, args) {
|
|
|
3355
3373
|
}
|
|
3356
3374
|
|
|
3357
3375
|
// packages/cli/src/commands/agent.ts
|
|
3358
|
-
import { resolve as
|
|
3376
|
+
import { resolve as resolve12 } from "path";
|
|
3359
3377
|
import {
|
|
3360
3378
|
agentId,
|
|
3361
3379
|
cleanupAgentRuntime,
|
|
@@ -3365,8 +3383,8 @@ import {
|
|
|
3365
3383
|
} from "@rig/runtime/control-plane/runtime/isolation";
|
|
3366
3384
|
|
|
3367
3385
|
// packages/cli/src/commands/_authority-runs.ts
|
|
3368
|
-
import { existsSync as
|
|
3369
|
-
import { resolve as
|
|
3386
|
+
import { existsSync as existsSync7 } from "fs";
|
|
3387
|
+
import { resolve as resolve11 } from "path";
|
|
3370
3388
|
import {
|
|
3371
3389
|
readAuthorityRun,
|
|
3372
3390
|
readJsonlFile as readJsonlFile2,
|
|
@@ -3388,8 +3406,8 @@ function normalizeRuntimeAdapter(value) {
|
|
|
3388
3406
|
return "claude-code";
|
|
3389
3407
|
}
|
|
3390
3408
|
function readLatestBeadRecord(projectRoot, taskId) {
|
|
3391
|
-
const issuesPath =
|
|
3392
|
-
if (!
|
|
3409
|
+
const issuesPath = resolve11(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
|
|
3410
|
+
if (!existsSync7(issuesPath)) {
|
|
3393
3411
|
return null;
|
|
3394
3412
|
}
|
|
3395
3413
|
let latest = null;
|
|
@@ -3456,7 +3474,7 @@ function upsertAgentAuthorityRun(projectRoot, input) {
|
|
|
3456
3474
|
} else if ("errorText" in next) {
|
|
3457
3475
|
delete next.errorText;
|
|
3458
3476
|
}
|
|
3459
|
-
writeJsonFile3(
|
|
3477
|
+
writeJsonFile3(resolve11(resolveAuthorityRunDir(projectRoot, input.runId), "run.json"), next);
|
|
3460
3478
|
return next;
|
|
3461
3479
|
}
|
|
3462
3480
|
|
|
@@ -3577,10 +3595,10 @@ async function executeAgent(context, args) {
|
|
|
3577
3595
|
status: "running",
|
|
3578
3596
|
startedAt: createdAt,
|
|
3579
3597
|
worktreePath: runtime.workspaceDir,
|
|
3580
|
-
artifactRoot:
|
|
3598
|
+
artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
|
|
3581
3599
|
logRoot: runtime.logsDir,
|
|
3582
|
-
sessionPath:
|
|
3583
|
-
sessionLogPath:
|
|
3600
|
+
sessionPath: resolve12(runtime.sessionDir, "session.json"),
|
|
3601
|
+
sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
|
|
3584
3602
|
pid: process.pid
|
|
3585
3603
|
});
|
|
3586
3604
|
const result = await runInAgentRuntime({
|
|
@@ -3600,10 +3618,10 @@ async function executeAgent(context, args) {
|
|
|
3600
3618
|
startedAt: createdAt,
|
|
3601
3619
|
completedAt: failedAt,
|
|
3602
3620
|
worktreePath: runtime.workspaceDir,
|
|
3603
|
-
artifactRoot:
|
|
3621
|
+
artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
|
|
3604
3622
|
logRoot: runtime.logsDir,
|
|
3605
|
-
sessionPath:
|
|
3606
|
-
sessionLogPath:
|
|
3623
|
+
sessionPath: resolve12(runtime.sessionDir, "session.json"),
|
|
3624
|
+
sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
|
|
3607
3625
|
pid: process.pid,
|
|
3608
3626
|
errorText: result.stderr ? result.stderr.trim() : `Agent runtime command failed (${result.exitCode})`
|
|
3609
3627
|
});
|
|
@@ -3620,10 +3638,10 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
|
|
|
3620
3638
|
startedAt: createdAt,
|
|
3621
3639
|
completedAt,
|
|
3622
3640
|
worktreePath: runtime.workspaceDir,
|
|
3623
|
-
artifactRoot:
|
|
3641
|
+
artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
|
|
3624
3642
|
logRoot: runtime.logsDir,
|
|
3625
|
-
sessionPath:
|
|
3626
|
-
sessionLogPath:
|
|
3643
|
+
sessionPath: resolve12(runtime.sessionDir, "session.json"),
|
|
3644
|
+
sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
|
|
3627
3645
|
pid: process.pid
|
|
3628
3646
|
});
|
|
3629
3647
|
return {
|
|
@@ -3697,7 +3715,7 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
|
|
|
3697
3715
|
import {
|
|
3698
3716
|
chmodSync,
|
|
3699
3717
|
copyFileSync as copyFileSync2,
|
|
3700
|
-
existsSync as
|
|
3718
|
+
existsSync as existsSync8,
|
|
3701
3719
|
mkdirSync as mkdirSync6,
|
|
3702
3720
|
readdirSync,
|
|
3703
3721
|
readlinkSync,
|
|
@@ -3707,7 +3725,7 @@ import {
|
|
|
3707
3725
|
unlinkSync
|
|
3708
3726
|
} from "fs";
|
|
3709
3727
|
import { homedir as homedir4 } from "os";
|
|
3710
|
-
import { resolve as
|
|
3728
|
+
import { resolve as resolve13 } from "path";
|
|
3711
3729
|
import { buildBinary as buildBinary2 } from "@rig/runtime/control-plane/runtime/isolation";
|
|
3712
3730
|
import {
|
|
3713
3731
|
computeRuntimeImageFingerprint,
|
|
@@ -3726,13 +3744,13 @@ async function runQuietBinaryProbe(binaryPath, args, cwd) {
|
|
|
3726
3744
|
|
|
3727
3745
|
// packages/cli/src/commands/dist.ts
|
|
3728
3746
|
function collectRigValidatorBuildTargets(input) {
|
|
3729
|
-
const validatorsRoot =
|
|
3730
|
-
if (!
|
|
3747
|
+
const validatorsRoot = resolve13(input.hostProjectRoot, "packages/runtime/src/control-plane/validators");
|
|
3748
|
+
if (!existsSync8(validatorsRoot))
|
|
3731
3749
|
return [];
|
|
3732
3750
|
const targets = [];
|
|
3733
3751
|
const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
3734
3752
|
for (const category of categories) {
|
|
3735
|
-
const categoryDir =
|
|
3753
|
+
const categoryDir = resolve13(validatorsRoot, category.name);
|
|
3736
3754
|
for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
|
|
3737
3755
|
if (!entry.isFile() || !entry.name.endsWith(".ts"))
|
|
3738
3756
|
continue;
|
|
@@ -3741,7 +3759,7 @@ function collectRigValidatorBuildTargets(input) {
|
|
|
3741
3759
|
continue;
|
|
3742
3760
|
targets.push({
|
|
3743
3761
|
source: `packages/runtime/src/control-plane/validators/${category.name}/${entry.name}`,
|
|
3744
|
-
dest:
|
|
3762
|
+
dest: resolve13(input.imageDir, `bin/validators/${category.name}-${check}`),
|
|
3745
3763
|
cwd: input.hostProjectRoot
|
|
3746
3764
|
});
|
|
3747
3765
|
}
|
|
@@ -3750,16 +3768,16 @@ function collectRigValidatorBuildTargets(input) {
|
|
|
3750
3768
|
}
|
|
3751
3769
|
async function findLatestDistBinary(projectRoot) {
|
|
3752
3770
|
const distRoot = resolveControlPlaneHostDistDir(projectRoot);
|
|
3753
|
-
if (!
|
|
3771
|
+
if (!existsSync8(distRoot)) {
|
|
3754
3772
|
return null;
|
|
3755
3773
|
}
|
|
3756
3774
|
const entries = readdirSync(distRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("rig-")).map((entry) => ({
|
|
3757
3775
|
name: entry.name,
|
|
3758
|
-
mtimeMs: statSync(
|
|
3776
|
+
mtimeMs: statSync(resolve13(distRoot, entry.name)).mtimeMs
|
|
3759
3777
|
})).sort((a, b) => b.mtimeMs - a.mtimeMs || b.name.localeCompare(a.name));
|
|
3760
3778
|
for (const { name } of entries) {
|
|
3761
|
-
const candidate =
|
|
3762
|
-
if (
|
|
3779
|
+
const candidate = resolve13(distRoot, name, "bin", "rig");
|
|
3780
|
+
if (existsSync8(candidate) && await isRunnableRigBinary(candidate, projectRoot)) {
|
|
3763
3781
|
return candidate;
|
|
3764
3782
|
}
|
|
3765
3783
|
}
|
|
@@ -3771,7 +3789,7 @@ async function isRunnableRigBinary(binaryPath, projectRoot) {
|
|
|
3771
3789
|
async function runDistDoctor(projectRoot) {
|
|
3772
3790
|
const bunPath = Bun.which("bun");
|
|
3773
3791
|
const rigPath = Bun.which("rig");
|
|
3774
|
-
const userBinDir =
|
|
3792
|
+
const userBinDir = resolve13(homedir4(), ".local/bin");
|
|
3775
3793
|
const userBinInPath = (process.env.PATH || "").split(":").filter(Boolean).includes(userBinDir);
|
|
3776
3794
|
let rigRunnable = false;
|
|
3777
3795
|
if (rigPath) {
|
|
@@ -3819,15 +3837,15 @@ async function executeDist(context, args) {
|
|
|
3819
3837
|
let source = await findLatestDistBinary(context.projectRoot);
|
|
3820
3838
|
let buildDir = null;
|
|
3821
3839
|
if (!source) {
|
|
3822
|
-
buildDir =
|
|
3840
|
+
buildDir = resolve13(resolveControlPlaneHostDistDir(context.projectRoot), `rig-install-${Date.now()}`);
|
|
3823
3841
|
await context.runCommand(["bun", "run", "packages/cli/bin/build-rig-binaries.ts", "--output-dir", buildDir]);
|
|
3824
|
-
source =
|
|
3842
|
+
source = resolve13(buildDir, "bin", "rig");
|
|
3825
3843
|
}
|
|
3826
|
-
if (!
|
|
3844
|
+
if (!existsSync8(source)) {
|
|
3827
3845
|
throw new CliError2(`Unable to locate rig binary at ${source}.`, 2);
|
|
3828
3846
|
}
|
|
3829
|
-
const installedPath =
|
|
3830
|
-
if (
|
|
3847
|
+
const installedPath = resolve13(installDir, "rig");
|
|
3848
|
+
if (existsSync8(installedPath)) {
|
|
3831
3849
|
unlinkSync(installedPath);
|
|
3832
3850
|
}
|
|
3833
3851
|
copyFileSync2(source, installedPath);
|
|
@@ -3869,22 +3887,22 @@ async function executeDist(context, args) {
|
|
|
3869
3887
|
requireNoExtraArgs(rest, "bun run rig dist rebuild-agent");
|
|
3870
3888
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
3871
3889
|
const currentId = computeRuntimeImageId(fp);
|
|
3872
|
-
const imagesDir =
|
|
3890
|
+
const imagesDir = resolve13(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
3873
3891
|
mkdirSync6(imagesDir, { recursive: true });
|
|
3874
3892
|
let pruned = 0;
|
|
3875
3893
|
for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
|
|
3876
3894
|
if (entry.isDirectory() && entry.name !== currentId) {
|
|
3877
|
-
rmSync4(
|
|
3895
|
+
rmSync4(resolve13(imagesDir, entry.name), { recursive: true, force: true });
|
|
3878
3896
|
pruned++;
|
|
3879
3897
|
}
|
|
3880
3898
|
}
|
|
3881
3899
|
if (pruned > 0 && context.outputMode === "text") {
|
|
3882
3900
|
console.log(`Pruned ${pruned} stale image(s).`);
|
|
3883
3901
|
}
|
|
3884
|
-
const imageDir =
|
|
3885
|
-
mkdirSync6(
|
|
3886
|
-
mkdirSync6(
|
|
3887
|
-
mkdirSync6(
|
|
3902
|
+
const imageDir = resolve13(imagesDir, currentId);
|
|
3903
|
+
mkdirSync6(resolve13(imageDir, "bin/hooks"), { recursive: true });
|
|
3904
|
+
mkdirSync6(resolve13(imageDir, "bin/plugins"), { recursive: true });
|
|
3905
|
+
mkdirSync6(resolve13(imageDir, "bin/validators"), { recursive: true });
|
|
3888
3906
|
const hookNames = [
|
|
3889
3907
|
"scope-guard",
|
|
3890
3908
|
"import-guard",
|
|
@@ -3898,25 +3916,25 @@ async function executeDist(context, args) {
|
|
|
3898
3916
|
];
|
|
3899
3917
|
const targets = [];
|
|
3900
3918
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || context.projectRoot;
|
|
3901
|
-
targets.push({ source: "packages/runtime/bin/rig-agent.ts", dest:
|
|
3902
|
-
targets.push({ source: "packages/runtime/bin/rig-agent-dispatch.ts", dest:
|
|
3919
|
+
targets.push({ source: "packages/runtime/bin/rig-agent.ts", dest: resolve13(imageDir, "bin/rig-agent"), cwd: hostProjectRoot });
|
|
3920
|
+
targets.push({ source: "packages/runtime/bin/rig-agent-dispatch.ts", dest: resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "rig-agent"), cwd: hostProjectRoot });
|
|
3903
3921
|
for (const hookName of hookNames) {
|
|
3904
3922
|
const src = `packages/runtime/src/control-plane/hooks/${hookName}.ts`;
|
|
3905
|
-
targets.push({ source: src, dest:
|
|
3906
|
-
targets.push({ source: src, dest:
|
|
3923
|
+
targets.push({ source: src, dest: resolve13(imageDir, `bin/hooks/${hookName}`), cwd: hostProjectRoot });
|
|
3924
|
+
targets.push({ source: src, dest: resolve13(resolveControlPlaneHostBinDir(context.projectRoot), `hooks/${hookName}`), cwd: hostProjectRoot });
|
|
3907
3925
|
}
|
|
3908
|
-
const pluginsDir =
|
|
3909
|
-
const binPluginsDir =
|
|
3910
|
-
const validatorsRoot =
|
|
3911
|
-
const binValidatorsDir =
|
|
3926
|
+
const pluginsDir = resolve13(context.projectRoot, "rig/plugins");
|
|
3927
|
+
const binPluginsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
|
|
3928
|
+
const validatorsRoot = resolve13(hostProjectRoot, "packages/runtime/src/control-plane/validators");
|
|
3929
|
+
const binValidatorsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
|
|
3912
3930
|
mkdirSync6(binPluginsDir, { recursive: true });
|
|
3913
3931
|
mkdirSync6(binValidatorsDir, { recursive: true });
|
|
3914
|
-
if (
|
|
3932
|
+
if (existsSync8(pluginsDir)) {
|
|
3915
3933
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
3916
3934
|
const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
3917
3935
|
if (!m)
|
|
3918
3936
|
continue;
|
|
3919
|
-
targets.push({ source: `rig/plugins/${entry.name}`, dest:
|
|
3937
|
+
targets.push({ source: `rig/plugins/${entry.name}`, dest: resolve13(imageDir, `bin/plugins/${m[1]}`), cwd: context.projectRoot });
|
|
3920
3938
|
}
|
|
3921
3939
|
}
|
|
3922
3940
|
targets.push(...collectRigValidatorBuildTargets({ contextProjectRoot: context.projectRoot, hostProjectRoot, imageDir }));
|
|
@@ -3927,17 +3945,17 @@ async function executeDist(context, args) {
|
|
|
3927
3945
|
const isValidator = dest.includes("/bin/validators/");
|
|
3928
3946
|
await buildBinary2(source, dest, cwd, isValidator ? { AGENT_BUN_PATH: Bun.which("bun") || "bun" } : { AGENT_PROJECT_ROOT: context.projectRoot });
|
|
3929
3947
|
}
|
|
3930
|
-
if (
|
|
3948
|
+
if (existsSync8(pluginsDir)) {
|
|
3931
3949
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
3932
3950
|
const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
3933
3951
|
if (!m)
|
|
3934
3952
|
continue;
|
|
3935
3953
|
const pluginName = m[1];
|
|
3936
|
-
const imageBin =
|
|
3954
|
+
const imageBin = resolve13(imageDir, `bin/plugins/${pluginName}`);
|
|
3937
3955
|
if (!pluginName)
|
|
3938
3956
|
continue;
|
|
3939
|
-
const symlinkPath =
|
|
3940
|
-
if (
|
|
3957
|
+
const symlinkPath = resolve13(binPluginsDir, pluginName);
|
|
3958
|
+
if (existsSync8(imageBin)) {
|
|
3941
3959
|
try {
|
|
3942
3960
|
unlinkSync(symlinkPath);
|
|
3943
3961
|
} catch {}
|
|
@@ -3945,10 +3963,10 @@ async function executeDist(context, args) {
|
|
|
3945
3963
|
}
|
|
3946
3964
|
}
|
|
3947
3965
|
}
|
|
3948
|
-
if (
|
|
3966
|
+
if (existsSync8(validatorsRoot)) {
|
|
3949
3967
|
const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
3950
3968
|
for (const category of categories) {
|
|
3951
|
-
const categoryDir =
|
|
3969
|
+
const categoryDir = resolve13(validatorsRoot, category.name);
|
|
3952
3970
|
for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
|
|
3953
3971
|
if (!entry.isFile() || !entry.name.endsWith(".ts"))
|
|
3954
3972
|
continue;
|
|
@@ -3956,9 +3974,9 @@ async function executeDist(context, args) {
|
|
|
3956
3974
|
if (!check || check === "index" || check === "shared")
|
|
3957
3975
|
continue;
|
|
3958
3976
|
const validatorName = `${category.name}-${check}`;
|
|
3959
|
-
const imageBin =
|
|
3960
|
-
const symlinkPath =
|
|
3961
|
-
if (
|
|
3977
|
+
const imageBin = resolve13(imageDir, `bin/validators/${validatorName}`);
|
|
3978
|
+
const symlinkPath = resolve13(binValidatorsDir, validatorName);
|
|
3979
|
+
if (existsSync8(imageBin)) {
|
|
3962
3980
|
try {
|
|
3963
3981
|
unlinkSync(symlinkPath);
|
|
3964
3982
|
} catch {}
|
|
@@ -3967,18 +3985,18 @@ async function executeDist(context, args) {
|
|
|
3967
3985
|
}
|
|
3968
3986
|
}
|
|
3969
3987
|
}
|
|
3970
|
-
const agentsDir =
|
|
3971
|
-
if (
|
|
3988
|
+
const agentsDir = resolve13(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "agents");
|
|
3989
|
+
if (existsSync8(agentsDir)) {
|
|
3972
3990
|
let relinkCount = 0;
|
|
3973
3991
|
for (const agentEntry of readdirSync(agentsDir, { withFileTypes: true })) {
|
|
3974
3992
|
if (!agentEntry.isDirectory())
|
|
3975
3993
|
continue;
|
|
3976
|
-
const agentBinDir =
|
|
3977
|
-
if (!
|
|
3994
|
+
const agentBinDir = resolve13(agentsDir, agentEntry.name, "worktree", ".rig", "bin");
|
|
3995
|
+
if (!existsSync8(agentBinDir))
|
|
3978
3996
|
continue;
|
|
3979
3997
|
const walkDir = (dir) => {
|
|
3980
3998
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
3981
|
-
const fullPath =
|
|
3999
|
+
const fullPath = resolve13(dir, entry.name);
|
|
3982
4000
|
if (entry.isDirectory()) {
|
|
3983
4001
|
walkDir(fullPath);
|
|
3984
4002
|
} else if (entry.isSymbolicLink()) {
|
|
@@ -4012,7 +4030,7 @@ async function executeDist(context, args) {
|
|
|
4012
4030
|
|
|
4013
4031
|
// packages/cli/src/commands/inbox.ts
|
|
4014
4032
|
import { writeFileSync as writeFileSync4 } from "fs";
|
|
4015
|
-
import { resolve as
|
|
4033
|
+
import { resolve as resolve14 } from "path";
|
|
4016
4034
|
import {
|
|
4017
4035
|
listAuthorityRuns,
|
|
4018
4036
|
readJsonlFile as readJsonlFile3,
|
|
@@ -4029,7 +4047,7 @@ async function executeInbox(context, args) {
|
|
|
4029
4047
|
pending = task.rest;
|
|
4030
4048
|
requireNoExtraArgs(pending, "bun run rig inbox approvals [--run <id>] [--task <id>]");
|
|
4031
4049
|
const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!run.value || entry.runId === run.value) && (!task.value || entry.taskId === task.value));
|
|
4032
|
-
const approvals = runs.flatMap((entry) => readJsonlFile3(
|
|
4050
|
+
const approvals = runs.flatMap((entry) => readJsonlFile3(resolve14(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "approvals.jsonl")).map((record) => ({
|
|
4033
4051
|
runId: entry.runId,
|
|
4034
4052
|
record
|
|
4035
4053
|
})));
|
|
@@ -4057,7 +4075,7 @@ async function executeInbox(context, args) {
|
|
|
4057
4075
|
if (decision.value !== "approve" && decision.value !== "reject") {
|
|
4058
4076
|
throw new CliError2("decision must be approve or reject.");
|
|
4059
4077
|
}
|
|
4060
|
-
const approvalsPath =
|
|
4078
|
+
const approvalsPath = resolve14(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
|
|
4061
4079
|
const approvals = readJsonlFile3(approvalsPath);
|
|
4062
4080
|
const resolvedAt = new Date().toISOString();
|
|
4063
4081
|
const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note: note3.value ?? null, resolvedAt } : entry);
|
|
@@ -4074,7 +4092,7 @@ async function executeInbox(context, args) {
|
|
|
4074
4092
|
pending = task.rest;
|
|
4075
4093
|
requireNoExtraArgs(pending, "bun run rig inbox inputs [--run <id>] [--task <id>]");
|
|
4076
4094
|
const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!run.value || entry.runId === run.value) && (!task.value || entry.taskId === task.value));
|
|
4077
|
-
const requests = runs.flatMap((entry) => readJsonlFile3(
|
|
4095
|
+
const requests = runs.flatMap((entry) => readJsonlFile3(resolve14(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "user-input.jsonl")).map((record) => ({
|
|
4078
4096
|
runId: entry.runId,
|
|
4079
4097
|
record
|
|
4080
4098
|
})));
|
|
@@ -4116,7 +4134,7 @@ async function executeInbox(context, args) {
|
|
|
4116
4134
|
const [key, ...restValue] = entry.split("=");
|
|
4117
4135
|
return [key, restValue.join("=")];
|
|
4118
4136
|
}));
|
|
4119
|
-
const requestsPath =
|
|
4137
|
+
const requestsPath = resolve14(resolveAuthorityRunDir2(context.projectRoot, run.value), "user-input.jsonl");
|
|
4120
4138
|
const requests = readJsonlFile3(requestsPath);
|
|
4121
4139
|
const resolvedAt = new Date().toISOString();
|
|
4122
4140
|
const next = requests.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", answers: parsedAnswers, respondedAt: resolvedAt, resolvedAt } : entry);
|
|
@@ -4131,14 +4149,14 @@ async function executeInbox(context, args) {
|
|
|
4131
4149
|
}
|
|
4132
4150
|
|
|
4133
4151
|
// packages/cli/src/commands/init.ts
|
|
4134
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
4152
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync7, readFileSync as readFileSync6, writeFileSync as writeFileSync5 } from "fs";
|
|
4135
4153
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
4136
|
-
import { resolve as
|
|
4154
|
+
import { resolve as resolve17 } from "path";
|
|
4137
4155
|
import { buildRigInitConfigSource } from "@rig/core";
|
|
4138
4156
|
|
|
4139
4157
|
// packages/cli/src/commands/_snapshot-upload.ts
|
|
4140
4158
|
import { mkdir, readdir, readFile, writeFile } from "fs/promises";
|
|
4141
|
-
import { dirname as dirname2, resolve as
|
|
4159
|
+
import { dirname as dirname2, resolve as resolve15, relative, sep } from "path";
|
|
4142
4160
|
var SNAPSHOT_ARCHIVE_VERSION = 1;
|
|
4143
4161
|
var SNAPSHOT_ARCHIVE_CONTENT_TYPE = "application/vnd.rig.snapshot+json";
|
|
4144
4162
|
var DEFAULT_EXCLUDED_DIRECTORIES = new Set([
|
|
@@ -4160,15 +4178,15 @@ function assertManifestPath(root, relativePath) {
|
|
|
4160
4178
|
if (!relativePath || relativePath.startsWith("/") || relativePath.includes("\x00")) {
|
|
4161
4179
|
throw new Error(`Invalid snapshot path: ${relativePath}`);
|
|
4162
4180
|
}
|
|
4163
|
-
const resolved =
|
|
4181
|
+
const resolved = resolve15(root, relativePath);
|
|
4164
4182
|
const relativeToRoot = relative(root, resolved);
|
|
4165
|
-
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." ||
|
|
4183
|
+
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || resolve15(relativeToRoot) === resolved) {
|
|
4166
4184
|
throw new Error(`Snapshot path escapes project root: ${relativePath}`);
|
|
4167
4185
|
}
|
|
4168
4186
|
return resolved;
|
|
4169
4187
|
}
|
|
4170
4188
|
async function buildSnapshotUploadManifest(projectRoot, options = {}) {
|
|
4171
|
-
const root =
|
|
4189
|
+
const root = resolve15(projectRoot);
|
|
4172
4190
|
const excludedDirectories = [...new Set([
|
|
4173
4191
|
...DEFAULT_EXCLUDED_DIRECTORIES,
|
|
4174
4192
|
...options.excludedDirectories ?? []
|
|
@@ -4180,7 +4198,7 @@ async function buildSnapshotUploadManifest(projectRoot, options = {}) {
|
|
|
4180
4198
|
for (const entry of entries) {
|
|
4181
4199
|
if (entry.isDirectory() && excludedSet.has(entry.name))
|
|
4182
4200
|
continue;
|
|
4183
|
-
const fullPath =
|
|
4201
|
+
const fullPath = resolve15(dir, entry.name);
|
|
4184
4202
|
if (entry.isDirectory()) {
|
|
4185
4203
|
await visit(fullPath);
|
|
4186
4204
|
continue;
|
|
@@ -4228,8 +4246,8 @@ async function uploadSnapshotArchiveViaServer(context, input) {
|
|
|
4228
4246
|
}
|
|
4229
4247
|
|
|
4230
4248
|
// packages/cli/src/commands/_doctor-checks.ts
|
|
4231
|
-
import { existsSync as
|
|
4232
|
-
import { resolve as
|
|
4249
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5 } from "fs";
|
|
4250
|
+
import { resolve as resolve16 } from "path";
|
|
4233
4251
|
import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
|
|
4234
4252
|
function check(id, label, status, detail, remediation) {
|
|
4235
4253
|
return {
|
|
@@ -4269,11 +4287,11 @@ function repoSlugFromConfig(config) {
|
|
|
4269
4287
|
function loadFallbackConfig(projectRoot) {
|
|
4270
4288
|
const candidates = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
|
|
4271
4289
|
for (const name of candidates) {
|
|
4272
|
-
const path =
|
|
4273
|
-
if (!
|
|
4290
|
+
const path = resolve16(projectRoot, name);
|
|
4291
|
+
if (!existsSync9(path))
|
|
4274
4292
|
continue;
|
|
4275
4293
|
try {
|
|
4276
|
-
const source =
|
|
4294
|
+
const source = readFileSync5(path, "utf8");
|
|
4277
4295
|
if (name.endsWith(".json"))
|
|
4278
4296
|
return JSON.parse(source);
|
|
4279
4297
|
const owner = source.match(/owner\s*:\s*["']([^"']+)["']/)?.[1];
|
|
@@ -4352,7 +4370,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4352
4370
|
checks.push(check("bun", `bun >= ${MIN_SUPPORTED_BUN_VERSION}`, isSupportedBunVersion(bunVersion) ? "pass" : "fail", `found ${bunVersion}`, `Install Bun ${MIN_SUPPORTED_BUN_VERSION} or newer.`), check("git", "git", which("git") ? "pass" : "fail", which("git") ?? undefined, "Install git and ensure it is on PATH."), check("jq", "jq", which("jq") ? "pass" : "warn", which("jq") ?? undefined, "Install jq (for example `brew install jq`)."));
|
|
4353
4371
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
4354
4372
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
4355
|
-
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) =>
|
|
4373
|
+
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync9(resolve16(projectRoot, name)));
|
|
4356
4374
|
checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "Run `rig init` or fix the config error."));
|
|
4357
4375
|
const taskSourceKind = config?.taskSource?.kind;
|
|
4358
4376
|
checks.push(taskSourceKind ? check("task-source", "task source configured", "pass", taskSourceKind) : check("task-source", "task source configured", "fail", "missing taskSource", "Configure taskSource in rig.config.ts."));
|
|
@@ -4447,10 +4465,10 @@ function countDoctorFailures(checks) {
|
|
|
4447
4465
|
}
|
|
4448
4466
|
|
|
4449
4467
|
// packages/cli/src/commands/init.ts
|
|
4450
|
-
var
|
|
4468
|
+
var RIG_CONFIG_PACKAGE_DIST_TAG = "latest";
|
|
4451
4469
|
var RIG_CONFIG_DEV_DEPENDENCIES = {
|
|
4452
|
-
"@rig/core": `npm:@h-rig/core@${
|
|
4453
|
-
"@rig/standard-plugin": `npm:@h-rig/standard-plugin@${
|
|
4470
|
+
"@rig/core": `npm:@h-rig/core@${RIG_CONFIG_PACKAGE_DIST_TAG}`,
|
|
4471
|
+
"@rig/standard-plugin": `npm:@h-rig/standard-plugin@${RIG_CONFIG_PACKAGE_DIST_TAG}`
|
|
4454
4472
|
};
|
|
4455
4473
|
function parseRepoSlugFromRemote(remoteUrl) {
|
|
4456
4474
|
const trimmed = remoteUrl.trim();
|
|
@@ -4470,20 +4488,20 @@ function parseRepoSlug(value) {
|
|
|
4470
4488
|
return { owner: match[1], repo: match[2], slug: `${match[1]}/${match[2]}` };
|
|
4471
4489
|
}
|
|
4472
4490
|
function ensureRigPrivateDirs(projectRoot) {
|
|
4473
|
-
const rigDir =
|
|
4474
|
-
mkdirSync7(
|
|
4475
|
-
mkdirSync7(
|
|
4476
|
-
mkdirSync7(
|
|
4477
|
-
mkdirSync7(
|
|
4478
|
-
mkdirSync7(
|
|
4479
|
-
const taskConfigPath =
|
|
4480
|
-
if (!
|
|
4491
|
+
const rigDir = resolve17(projectRoot, ".rig");
|
|
4492
|
+
mkdirSync7(resolve17(rigDir, "state"), { recursive: true });
|
|
4493
|
+
mkdirSync7(resolve17(rigDir, "logs"), { recursive: true });
|
|
4494
|
+
mkdirSync7(resolve17(rigDir, "runs"), { recursive: true });
|
|
4495
|
+
mkdirSync7(resolve17(rigDir, "tmp"), { recursive: true });
|
|
4496
|
+
mkdirSync7(resolve17(projectRoot, "artifacts"), { recursive: true });
|
|
4497
|
+
const taskConfigPath = resolve17(rigDir, "task-config.json");
|
|
4498
|
+
if (!existsSync10(taskConfigPath))
|
|
4481
4499
|
writeFileSync5(taskConfigPath, `{}
|
|
4482
4500
|
`, "utf-8");
|
|
4483
4501
|
}
|
|
4484
4502
|
function ensureGitignoreEntries(projectRoot) {
|
|
4485
|
-
const path =
|
|
4486
|
-
const existing =
|
|
4503
|
+
const path = resolve17(projectRoot, ".gitignore");
|
|
4504
|
+
const existing = existsSync10(path) ? readFileSync6(path, "utf8") : "";
|
|
4487
4505
|
const entries = [".rig/state/", ".rig/logs/", ".rig/runs/", ".rig/tmp/"];
|
|
4488
4506
|
const missing = entries.filter((entry) => !existing.split(/\r?\n/).includes(entry));
|
|
4489
4507
|
if (missing.length === 0)
|
|
@@ -4496,14 +4514,14 @@ function ensureGitignoreEntries(projectRoot) {
|
|
|
4496
4514
|
`, "utf8");
|
|
4497
4515
|
}
|
|
4498
4516
|
function ensureRigConfigPackageDependencies(projectRoot) {
|
|
4499
|
-
const path =
|
|
4500
|
-
const existing =
|
|
4517
|
+
const path = resolve17(projectRoot, "package.json");
|
|
4518
|
+
const existing = existsSync10(path) ? JSON.parse(readFileSync6(path, "utf8")) : {};
|
|
4501
4519
|
const devDependencies = existing.devDependencies && typeof existing.devDependencies === "object" && !Array.isArray(existing.devDependencies) ? { ...existing.devDependencies } : {};
|
|
4502
4520
|
for (const [name, spec] of Object.entries(RIG_CONFIG_DEV_DEPENDENCIES)) {
|
|
4503
4521
|
devDependencies[name] = spec;
|
|
4504
4522
|
}
|
|
4505
4523
|
const next = {
|
|
4506
|
-
...
|
|
4524
|
+
...existsSync10(path) ? existing : { name: "rig-project", private: true },
|
|
4507
4525
|
devDependencies
|
|
4508
4526
|
};
|
|
4509
4527
|
writeFileSync5(path, `${JSON.stringify(next, null, 2)}
|
|
@@ -4573,15 +4591,54 @@ async function promptSelect(prompts, options) {
|
|
|
4573
4591
|
throw new CliError2("Init cancelled.", 1);
|
|
4574
4592
|
return String(value);
|
|
4575
4593
|
}
|
|
4576
|
-
|
|
4594
|
+
function sleep2(ms) {
|
|
4595
|
+
return new Promise((resolve18) => setTimeout(resolve18, ms));
|
|
4596
|
+
}
|
|
4597
|
+
function positiveIntFromEnv(name, fallback) {
|
|
4598
|
+
const value = Number.parseInt(process.env[name] ?? "", 10);
|
|
4599
|
+
return Number.isFinite(value) && value >= 0 ? value : fallback;
|
|
4600
|
+
}
|
|
4601
|
+
function apiSessionTokenFrom(payload) {
|
|
4602
|
+
if (!payload || typeof payload !== "object" || Array.isArray(payload))
|
|
4603
|
+
return null;
|
|
4604
|
+
const token = payload.apiSessionToken;
|
|
4605
|
+
return typeof token === "string" && token.trim() ? token.trim() : null;
|
|
4606
|
+
}
|
|
4607
|
+
function writeRemoteGitHubAuthState(projectRoot, input) {
|
|
4608
|
+
writeFileSync5(resolve17(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
|
|
4609
|
+
authenticated: true,
|
|
4610
|
+
source: input.source,
|
|
4611
|
+
storedOnServer: true,
|
|
4612
|
+
selectedRepo: input.selectedRepo,
|
|
4613
|
+
...input.apiSessionToken ? { apiSessionToken: input.apiSessionToken } : {},
|
|
4614
|
+
updatedAt: new Date().toISOString()
|
|
4615
|
+
}, null, 2)}
|
|
4616
|
+
`, "utf8");
|
|
4617
|
+
}
|
|
4618
|
+
async function pollDeviceAuthUntilComplete(context, pollId, firstPayload) {
|
|
4577
4619
|
if (typeof pollId !== "string" || !pollId.trim())
|
|
4578
4620
|
return null;
|
|
4579
|
-
const
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4621
|
+
const intervalSeconds = typeof firstPayload.interval === "number" && Number.isFinite(firstPayload.interval) && firstPayload.interval > 0 ? firstPayload.interval : 5;
|
|
4622
|
+
const timeoutMs = positiveIntFromEnv("RIG_DEVICE_AUTH_POLL_TIMEOUT_MS", 300000);
|
|
4623
|
+
const intervalMs = positiveIntFromEnv("RIG_DEVICE_AUTH_POLL_INTERVAL_MS", Math.max(1000, intervalSeconds * 1000));
|
|
4624
|
+
const deadline = Date.now() + timeoutMs;
|
|
4625
|
+
let last = null;
|
|
4626
|
+
do {
|
|
4627
|
+
const payload = await requestServerJson(context, "/api/github/auth/device/poll", {
|
|
4628
|
+
method: "POST",
|
|
4629
|
+
headers: { "content-type": "application/json" },
|
|
4630
|
+
body: JSON.stringify({ pollId })
|
|
4631
|
+
}).catch(() => null);
|
|
4632
|
+
last = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : null;
|
|
4633
|
+
const status = typeof last?.status === "string" ? last.status : null;
|
|
4634
|
+
if (status === "signed-in" || status === "expired" || status === "cancelled" || status === "failed") {
|
|
4635
|
+
return last;
|
|
4636
|
+
}
|
|
4637
|
+
if (timeoutMs <= 0)
|
|
4638
|
+
return last;
|
|
4639
|
+
await sleep2(intervalMs);
|
|
4640
|
+
} while (Date.now() < deadline);
|
|
4641
|
+
return last;
|
|
4585
4642
|
}
|
|
4586
4643
|
async function runControlPlaneInit(context, options) {
|
|
4587
4644
|
const projectRoot = context.projectRoot;
|
|
@@ -4604,9 +4661,9 @@ async function runControlPlaneInit(context, options) {
|
|
|
4604
4661
|
});
|
|
4605
4662
|
ensureRigPrivateDirs(projectRoot);
|
|
4606
4663
|
ensureGitignoreEntries(projectRoot);
|
|
4607
|
-
const configTsPath =
|
|
4608
|
-
const configJsonPath =
|
|
4609
|
-
const configExists =
|
|
4664
|
+
const configTsPath = resolve17(projectRoot, "rig.config.ts");
|
|
4665
|
+
const configJsonPath = resolve17(projectRoot, "rig.config.json");
|
|
4666
|
+
const configExists = existsSync10(configTsPath) || existsSync10(configJsonPath);
|
|
4610
4667
|
if (!options.privateStateOnly) {
|
|
4611
4668
|
if (configExists && !options.repair) {
|
|
4612
4669
|
if (context.outputMode !== "json")
|
|
@@ -4622,7 +4679,7 @@ async function runControlPlaneInit(context, options) {
|
|
|
4622
4679
|
}
|
|
4623
4680
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
4624
4681
|
}
|
|
4625
|
-
writeFileSync5(
|
|
4682
|
+
writeFileSync5(resolve17(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
|
|
4626
4683
|
`, "utf8");
|
|
4627
4684
|
const checkout = checkoutForInit(projectRoot, serverKind, options.remoteCheckout);
|
|
4628
4685
|
let uploadedSnapshot = null;
|
|
@@ -4644,10 +4701,14 @@ async function runControlPlaneInit(context, options) {
|
|
|
4644
4701
|
const token = authMethod === "gh" && !options.githubToken ? readGhAuthToken() : options.githubToken?.trim();
|
|
4645
4702
|
if (token) {
|
|
4646
4703
|
githubAuth = await postGitHubTokenViaServer(context, token, { selectedRepo: repo.slug });
|
|
4647
|
-
|
|
4704
|
+
const apiSessionToken = apiSessionTokenFrom(githubAuth);
|
|
4705
|
+
setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? token);
|
|
4648
4706
|
if (serverKind === "remote") {
|
|
4649
|
-
|
|
4650
|
-
|
|
4707
|
+
writeRemoteGitHubAuthState(projectRoot, {
|
|
4708
|
+
source: authMethod === "gh" ? "gh" : "init-token",
|
|
4709
|
+
selectedRepo: repo.slug,
|
|
4710
|
+
apiSessionToken
|
|
4711
|
+
});
|
|
4651
4712
|
}
|
|
4652
4713
|
} else if (authMethod === "device") {
|
|
4653
4714
|
const payload = await requestServerJson(context, "/api/github/auth/device/start", {
|
|
@@ -4656,9 +4717,22 @@ async function runControlPlaneInit(context, options) {
|
|
|
4656
4717
|
body: JSON.stringify({ repoSlug: repo.slug })
|
|
4657
4718
|
});
|
|
4658
4719
|
deviceAuth = payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
4659
|
-
|
|
4660
|
-
|
|
4720
|
+
if (context.outputMode !== "json") {
|
|
4721
|
+
const verificationUri = String(deviceAuth.verificationUri ?? deviceAuth.verification_uri ?? deviceAuth.verification_uri_complete ?? "the verification URL returned by the server");
|
|
4722
|
+
const userCode = String(deviceAuth.userCode ?? deviceAuth.user_code ?? "the returned user code");
|
|
4723
|
+
console.log(`GitHub device flow: open ${verificationUri} and enter ${userCode}. Waiting for authorization...`);
|
|
4724
|
+
}
|
|
4725
|
+
const completed = await pollDeviceAuthUntilComplete(context, deviceAuth.pollId, deviceAuth);
|
|
4726
|
+
if (completed) {
|
|
4727
|
+
const apiSessionToken = apiSessionTokenFrom(completed);
|
|
4728
|
+
if (apiSessionToken) {
|
|
4729
|
+
setGitHubBearerTokenForCurrentProcess(apiSessionToken);
|
|
4730
|
+
if (serverKind === "remote") {
|
|
4731
|
+
writeRemoteGitHubAuthState(projectRoot, { source: "device", selectedRepo: repo.slug, apiSessionToken });
|
|
4732
|
+
}
|
|
4733
|
+
}
|
|
4661
4734
|
deviceAuth = { ...deviceAuth, poll: completed, completed: completed.status === "signed-in" };
|
|
4735
|
+
}
|
|
4662
4736
|
}
|
|
4663
4737
|
let remoteCheckoutPreparation = null;
|
|
4664
4738
|
if (serverKind === "remote" && options.remoteCheckout?.kind !== "uploaded-snapshot") {
|
|
@@ -4678,6 +4752,12 @@ async function runControlPlaneInit(context, options) {
|
|
|
4678
4752
|
});
|
|
4679
4753
|
const checkoutPath = typeof checkout.path === "string" ? checkout.path : null;
|
|
4680
4754
|
const serverRootSwitch = serverKind === "remote" && checkoutPath ? await switchServerProjectRootViaServer(context, checkoutPath) : null;
|
|
4755
|
+
if (serverRootSwitch && token) {
|
|
4756
|
+
githubAuth = await postGitHubTokenViaServer(context, token, { selectedRepo: repo.slug, projectRoot: checkoutPath ?? undefined });
|
|
4757
|
+
const apiSessionToken = apiSessionTokenFrom(githubAuth);
|
|
4758
|
+
setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? token);
|
|
4759
|
+
writeRemoteGitHubAuthState(projectRoot, { source: authMethod === "gh" ? "gh" : "init-token", selectedRepo: repo.slug, apiSessionToken });
|
|
4760
|
+
}
|
|
4681
4761
|
const activeProjectRegistration = serverRootSwitch ? await registerProjectViaServer(context, { repoSlug: repo.slug, checkout }) : null;
|
|
4682
4762
|
const pi = serverKind === "remote" ? await ensureRemotePiRigInstalled({ requestJson: (pathname, init) => requestServerJson(context, pathname, init) }).catch((error) => ({
|
|
4683
4763
|
remote: true,
|
|
@@ -4787,7 +4867,7 @@ function parseInitOptions(args) {
|
|
|
4787
4867
|
async function runInteractiveControlPlaneInit(context, prompts) {
|
|
4788
4868
|
prompts.intro?.("Initialize a Rig control-plane project");
|
|
4789
4869
|
const projectRoot = context.projectRoot;
|
|
4790
|
-
const existingConfig =
|
|
4870
|
+
const existingConfig = existsSync10(resolve17(projectRoot, "rig.config.ts")) || existsSync10(resolve17(projectRoot, "rig.config.json"));
|
|
4791
4871
|
let repair = false;
|
|
4792
4872
|
let privateStateOnly = false;
|
|
4793
4873
|
if (existingConfig) {
|
|
@@ -4887,7 +4967,7 @@ async function runInteractiveControlPlaneInit(context, prompts) {
|
|
|
4887
4967
|
});
|
|
4888
4968
|
const details = result.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : {};
|
|
4889
4969
|
const deviceAuth = details.deviceAuth && typeof details.deviceAuth === "object" && !Array.isArray(details.deviceAuth) ? details.deviceAuth : null;
|
|
4890
|
-
const deviceMessage = deviceAuth ? ` GitHub device flow: open ${String(deviceAuth.verification_uri ?? deviceAuth.verification_uri_complete ?? "the verification URL returned by the server")} and enter ${String(deviceAuth.user_code ?? "the returned user code")}.` : "";
|
|
4970
|
+
const deviceMessage = deviceAuth ? ` GitHub device flow: open ${String(deviceAuth.verificationUri ?? deviceAuth.verification_uri ?? deviceAuth.verification_uri_complete ?? "the verification URL returned by the server")} and enter ${String(deviceAuth.userCode ?? deviceAuth.user_code ?? "the returned user code")}.` : "";
|
|
4891
4971
|
prompts.outro?.(`Rig project initialized.${deviceMessage} Next: rig doctor && rig task list`);
|
|
4892
4972
|
return result;
|
|
4893
4973
|
}
|
|
@@ -5049,8 +5129,8 @@ async function executeDoctor(context, args) {
|
|
|
5049
5129
|
}
|
|
5050
5130
|
|
|
5051
5131
|
// packages/cli/src/commands/_run-driver-helpers.ts
|
|
5052
|
-
import { readFileSync as
|
|
5053
|
-
import { resolve as
|
|
5132
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
5133
|
+
import { resolve as resolve18 } from "path";
|
|
5054
5134
|
import {
|
|
5055
5135
|
appendJsonlRecord as appendJsonlRecord2,
|
|
5056
5136
|
readAuthorityRun as readAuthorityRun2,
|
|
@@ -5070,7 +5150,7 @@ function patchAuthorityRun(projectRoot, runId, patch) {
|
|
|
5070
5150
|
...patch,
|
|
5071
5151
|
updatedAt: new Date().toISOString()
|
|
5072
5152
|
};
|
|
5073
|
-
writeJsonFile4(
|
|
5153
|
+
writeJsonFile4(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), next);
|
|
5074
5154
|
return next;
|
|
5075
5155
|
}
|
|
5076
5156
|
function touchAuthorityRun(projectRoot, runId) {
|
|
@@ -5078,21 +5158,21 @@ function touchAuthorityRun(projectRoot, runId) {
|
|
|
5078
5158
|
if (!current) {
|
|
5079
5159
|
return;
|
|
5080
5160
|
}
|
|
5081
|
-
writeJsonFile4(
|
|
5161
|
+
writeJsonFile4(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), {
|
|
5082
5162
|
...current,
|
|
5083
5163
|
updatedAt: new Date().toISOString()
|
|
5084
5164
|
});
|
|
5085
5165
|
}
|
|
5086
5166
|
function appendRunTimeline(projectRoot, runId, value) {
|
|
5087
|
-
appendJsonlRecord2(
|
|
5167
|
+
appendJsonlRecord2(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), value);
|
|
5088
5168
|
touchAuthorityRun(projectRoot, runId);
|
|
5089
5169
|
}
|
|
5090
5170
|
function appendRunLog(projectRoot, runId, value) {
|
|
5091
|
-
appendJsonlRecord2(
|
|
5171
|
+
appendJsonlRecord2(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "logs.jsonl"), value);
|
|
5092
5172
|
touchAuthorityRun(projectRoot, runId);
|
|
5093
5173
|
}
|
|
5094
5174
|
function appendRunAction(projectRoot, runId, value) {
|
|
5095
|
-
appendJsonlRecord2(
|
|
5175
|
+
appendJsonlRecord2(resolve18(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), {
|
|
5096
5176
|
id: value.id,
|
|
5097
5177
|
type: "action",
|
|
5098
5178
|
actionType: value.actionType,
|
|
@@ -5163,7 +5243,7 @@ function buildRunPrompt(input) {
|
|
|
5163
5243
|
})();
|
|
5164
5244
|
const scopeText = (() => {
|
|
5165
5245
|
try {
|
|
5166
|
-
const parsed = JSON.parse(
|
|
5246
|
+
const parsed = JSON.parse(readFileSync7(resolveControlPlaneTaskConfigPath(input.projectRoot), "utf8"));
|
|
5167
5247
|
const entry = parsed[input.taskId] ?? {};
|
|
5168
5248
|
const scope = Array.isArray(entry.scope) ? entry.scope.filter((item) => typeof item === "string") : [];
|
|
5169
5249
|
const validation = Array.isArray(entry.validation) ? entry.validation.filter((item) => typeof item === "string") : [];
|
|
@@ -5276,8 +5356,8 @@ function renderSourceScopeValidation(task, validation) {
|
|
|
5276
5356
|
}
|
|
5277
5357
|
|
|
5278
5358
|
// packages/cli/src/commands/inspect.ts
|
|
5279
|
-
import { existsSync as
|
|
5280
|
-
import { resolve as
|
|
5359
|
+
import { existsSync as existsSync11, readFileSync as readFileSync8 } from "fs";
|
|
5360
|
+
import { resolve as resolve19 } from "path";
|
|
5281
5361
|
import {
|
|
5282
5362
|
listAuthorityRuns as listAuthorityRuns2,
|
|
5283
5363
|
readAuthorityRun as readAuthorityRun3,
|
|
@@ -5298,8 +5378,8 @@ async function executeInspect(context, args) {
|
|
|
5298
5378
|
if (!latestRun) {
|
|
5299
5379
|
throw new CliError2(`No runs found for ${requiredTask}.`);
|
|
5300
5380
|
}
|
|
5301
|
-
const logsPath =
|
|
5302
|
-
if (!
|
|
5381
|
+
const logsPath = resolve19(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
5382
|
+
if (!existsSync11(logsPath)) {
|
|
5303
5383
|
throw new CliError2(`No logs found for run ${latestRun.runId}.`);
|
|
5304
5384
|
}
|
|
5305
5385
|
await context.runCommand(["cat", logsPath]);
|
|
@@ -5309,7 +5389,7 @@ async function executeInspect(context, args) {
|
|
|
5309
5389
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5310
5390
|
requireNoExtraArgs(remaining, "bun run rig inspect artifacts --task <beads-id>");
|
|
5311
5391
|
const requiredTask = requireTask(task, "bun run rig inspect artifacts --task <beads-id>");
|
|
5312
|
-
const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) =>
|
|
5392
|
+
const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync11(path));
|
|
5313
5393
|
if (!artifactRoot) {
|
|
5314
5394
|
throw new CliError2(`No artifacts found for ${requiredTask}.`);
|
|
5315
5395
|
}
|
|
@@ -5366,10 +5446,10 @@ async function executeInspect(context, args) {
|
|
|
5366
5446
|
case "failures": {
|
|
5367
5447
|
requireNoExtraArgs(rest, "bun run rig inspect failures");
|
|
5368
5448
|
const failed = resolveHarnessPaths2(context.projectRoot).failedApproachesPath;
|
|
5369
|
-
if (!
|
|
5449
|
+
if (!existsSync11(failed)) {
|
|
5370
5450
|
console.log("No failures recorded.");
|
|
5371
5451
|
} else {
|
|
5372
|
-
process.stdout.write(
|
|
5452
|
+
process.stdout.write(readFileSync8(failed, "utf-8"));
|
|
5373
5453
|
}
|
|
5374
5454
|
return { ok: true, group: "inspect", command };
|
|
5375
5455
|
}
|
|
@@ -5386,11 +5466,11 @@ async function executeInspect(context, args) {
|
|
|
5386
5466
|
return { ok: true, group: "inspect", command };
|
|
5387
5467
|
case "audit": {
|
|
5388
5468
|
requireNoExtraArgs(rest, "bun run rig inspect audit");
|
|
5389
|
-
const auditPath =
|
|
5390
|
-
if (!
|
|
5469
|
+
const auditPath = resolve19(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
|
|
5470
|
+
if (!existsSync11(auditPath)) {
|
|
5391
5471
|
console.log("No audit log found.");
|
|
5392
5472
|
} else {
|
|
5393
|
-
const lines =
|
|
5473
|
+
const lines = readFileSync8(auditPath, "utf-8").split(/\r?\n/).filter(Boolean).slice(-20);
|
|
5394
5474
|
for (const line of lines) {
|
|
5395
5475
|
console.log(line);
|
|
5396
5476
|
}
|
|
@@ -6019,8 +6099,8 @@ async function executeRemote(context, args) {
|
|
|
6019
6099
|
}
|
|
6020
6100
|
|
|
6021
6101
|
// packages/cli/src/commands/run.ts
|
|
6022
|
-
import { existsSync as
|
|
6023
|
-
import { resolve as
|
|
6102
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
6103
|
+
import { resolve as resolve20 } from "path";
|
|
6024
6104
|
import { createInterface as createInterface2 } from "readline/promises";
|
|
6025
6105
|
import {
|
|
6026
6106
|
listAuthorityRuns as listAuthorityRuns3,
|
|
@@ -6299,7 +6379,7 @@ async function executeRun(context, args) {
|
|
|
6299
6379
|
if (!run.value) {
|
|
6300
6380
|
throw new CliError2("run timeline requires --run <id>.");
|
|
6301
6381
|
}
|
|
6302
|
-
const timelinePath =
|
|
6382
|
+
const timelinePath = resolve20(resolveAuthorityRunDir5(context.projectRoot, run.value), "timeline.jsonl");
|
|
6303
6383
|
const printEvents = () => {
|
|
6304
6384
|
const events2 = readJsonlFile4(timelinePath);
|
|
6305
6385
|
if (context.outputMode === "text") {
|
|
@@ -6311,12 +6391,12 @@ async function executeRun(context, args) {
|
|
|
6311
6391
|
};
|
|
6312
6392
|
const events = printEvents();
|
|
6313
6393
|
if (follow.value && context.outputMode === "text") {
|
|
6314
|
-
let lastLength =
|
|
6394
|
+
let lastLength = existsSync12(timelinePath) ? readFileSync9(timelinePath, "utf8").length : 0;
|
|
6315
6395
|
while (true) {
|
|
6316
6396
|
await Bun.sleep(1000);
|
|
6317
|
-
if (!
|
|
6397
|
+
if (!existsSync12(timelinePath))
|
|
6318
6398
|
continue;
|
|
6319
|
-
const next =
|
|
6399
|
+
const next = readFileSync9(timelinePath, "utf8");
|
|
6320
6400
|
if (next.length <= lastLength)
|
|
6321
6401
|
continue;
|
|
6322
6402
|
const delta = next.slice(lastLength);
|
|
@@ -6602,10 +6682,10 @@ async function executeServer(context, args, options) {
|
|
|
6602
6682
|
}
|
|
6603
6683
|
|
|
6604
6684
|
// packages/cli/src/commands/task.ts
|
|
6605
|
-
import { readFileSync as
|
|
6685
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
6606
6686
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
6607
6687
|
import { createInterface as createInterface4 } from "readline/promises";
|
|
6608
|
-
import { resolve as
|
|
6688
|
+
import { resolve as resolve21 } from "path";
|
|
6609
6689
|
import {
|
|
6610
6690
|
taskArtifactDir,
|
|
6611
6691
|
taskArtifacts,
|
|
@@ -6936,7 +7016,7 @@ async function executeTask(context, args, options) {
|
|
|
6936
7016
|
const fileFlag = takeOption(rest.slice(1), "--file");
|
|
6937
7017
|
let content;
|
|
6938
7018
|
if (fileFlag.value) {
|
|
6939
|
-
content =
|
|
7019
|
+
content = readFileSync10(resolve21(context.projectRoot, fileFlag.value), "utf-8");
|
|
6940
7020
|
} else {
|
|
6941
7021
|
content = await readStdin();
|
|
6942
7022
|
}
|
|
@@ -7157,8 +7237,8 @@ async function executeTask(context, args, options) {
|
|
|
7157
7237
|
}
|
|
7158
7238
|
|
|
7159
7239
|
// packages/cli/src/commands/task-run-driver.ts
|
|
7160
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
7161
|
-
import { resolve as
|
|
7240
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
7241
|
+
import { resolve as resolve22 } from "path";
|
|
7162
7242
|
import { spawn as spawn2, spawnSync as spawnSync5 } from "child_process";
|
|
7163
7243
|
import { createInterface as createLineInterface } from "readline";
|
|
7164
7244
|
import { loadConfig as loadConfig2 } from "@rig/core/load-config";
|
|
@@ -7192,7 +7272,24 @@ import {
|
|
|
7192
7272
|
commitRunChanges,
|
|
7193
7273
|
runPrAutomation
|
|
7194
7274
|
} from "@rig/runtime/control-plane/native/pr-automation";
|
|
7275
|
+
function looksLikeGitHubToken(value) {
|
|
7276
|
+
const token = value?.trim();
|
|
7277
|
+
if (!token)
|
|
7278
|
+
return false;
|
|
7279
|
+
return /^(gh[opusr]_|github_pat_)/.test(token);
|
|
7280
|
+
}
|
|
7281
|
+
function githubBridgeEnv(token) {
|
|
7282
|
+
const clean = token?.trim();
|
|
7283
|
+
if (!clean)
|
|
7284
|
+
return {};
|
|
7285
|
+
return {
|
|
7286
|
+
RIG_GITHUB_TOKEN: clean,
|
|
7287
|
+
GITHUB_TOKEN: clean,
|
|
7288
|
+
GH_TOKEN: clean
|
|
7289
|
+
};
|
|
7290
|
+
}
|
|
7195
7291
|
function buildPiRigBridgeEnv(input) {
|
|
7292
|
+
const githubToken = input.githubToken?.trim() || (looksLikeGitHubToken(input.authToken) ? input.authToken.trim() : "");
|
|
7196
7293
|
return {
|
|
7197
7294
|
RIG_PROJECT_ROOT: input.projectRoot,
|
|
7198
7295
|
PROJECT_RIG_ROOT: input.projectRoot,
|
|
@@ -7202,7 +7299,7 @@ function buildPiRigBridgeEnv(input) {
|
|
|
7202
7299
|
RIG_RUNTIME_ADAPTER: "pi",
|
|
7203
7300
|
...input.serverUrl ? { RIG_SERVER_URL: input.serverUrl } : {},
|
|
7204
7301
|
...input.authToken ? { RIG_AUTH_TOKEN: input.authToken } : {},
|
|
7205
|
-
...
|
|
7302
|
+
...githubBridgeEnv(githubToken)
|
|
7206
7303
|
};
|
|
7207
7304
|
}
|
|
7208
7305
|
function runGitSync(cwd, args, input) {
|
|
@@ -7224,12 +7321,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
|
|
|
7224
7321
|
return 0;
|
|
7225
7322
|
let copied = 0;
|
|
7226
7323
|
for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
|
|
7227
|
-
const sourcePath =
|
|
7228
|
-
const targetPath =
|
|
7324
|
+
const sourcePath = resolve22(sourceRoot, relativePath);
|
|
7325
|
+
const targetPath = resolve22(targetRoot, relativePath);
|
|
7229
7326
|
try {
|
|
7230
7327
|
if (!statSync2(sourcePath).isFile())
|
|
7231
7328
|
continue;
|
|
7232
|
-
mkdirSync8(
|
|
7329
|
+
mkdirSync8(resolve22(targetPath, ".."), { recursive: true });
|
|
7233
7330
|
copyFileSync3(sourcePath, targetPath);
|
|
7234
7331
|
copied += 1;
|
|
7235
7332
|
} catch {}
|
|
@@ -7263,6 +7360,14 @@ function buildTaskRunReviewEnv(config) {
|
|
|
7263
7360
|
...review?.provider ? { AI_REVIEW_PROVIDER: review.provider } : {}
|
|
7264
7361
|
};
|
|
7265
7362
|
}
|
|
7363
|
+
function buildDirtyBaselineHandshakeEnv(input) {
|
|
7364
|
+
if (input.baselineMode !== "dirty-snapshot")
|
|
7365
|
+
return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
|
|
7366
|
+
return {
|
|
7367
|
+
RIG_BASELINE_MODE: "dirty-snapshot",
|
|
7368
|
+
RIG_DIRTY_BASELINE_READY_FILE: resolve22(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
|
|
7369
|
+
};
|
|
7370
|
+
}
|
|
7266
7371
|
function positiveInt(value, fallback) {
|
|
7267
7372
|
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
|
|
7268
7373
|
}
|
|
@@ -7371,9 +7476,9 @@ function createCommandRunner(binary) {
|
|
|
7371
7476
|
const stderrChunks = [];
|
|
7372
7477
|
child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
7373
7478
|
child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
7374
|
-
return await new Promise((
|
|
7375
|
-
child.once("error", (error) =>
|
|
7376
|
-
child.once("close", (code) =>
|
|
7479
|
+
return await new Promise((resolve23) => {
|
|
7480
|
+
child.once("error", (error) => resolve23({ exitCode: 1, stderr: error.message }));
|
|
7481
|
+
child.once("close", (code) => resolve23({
|
|
7377
7482
|
exitCode: code ?? 1,
|
|
7378
7483
|
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
7379
7484
|
stderr: Buffer.concat(stderrChunks).toString("utf8")
|
|
@@ -7569,7 +7674,7 @@ function summarizeValidationFailure(projectRoot, taskId2) {
|
|
|
7569
7674
|
return null;
|
|
7570
7675
|
}
|
|
7571
7676
|
for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId2)) {
|
|
7572
|
-
const summary = readJsonFile3(
|
|
7677
|
+
const summary = readJsonFile3(resolve22(artifactDir, "validation-summary.json"), null);
|
|
7573
7678
|
if (!summary || summary.status !== "fail") {
|
|
7574
7679
|
continue;
|
|
7575
7680
|
}
|
|
@@ -7650,9 +7755,9 @@ function readTaskRunAcceptedArtifactState(input) {
|
|
|
7650
7755
|
if (!input.taskId || !input.workspaceDir) {
|
|
7651
7756
|
return { accepted: false, reason: null };
|
|
7652
7757
|
}
|
|
7653
|
-
const artifactDir =
|
|
7654
|
-
const reviewStatusPath =
|
|
7655
|
-
const taskResultPath =
|
|
7758
|
+
const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
|
|
7759
|
+
const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
|
|
7760
|
+
const taskResultPath = resolve22(artifactDir, "task-result.json");
|
|
7656
7761
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
7657
7762
|
if (reviewStatus !== "APPROVED") {
|
|
7658
7763
|
return { accepted: false, reason: null };
|
|
@@ -7689,12 +7794,12 @@ function resolveTaskRunRetryContext(input) {
|
|
|
7689
7794
|
if (!input.taskId || !input.workspaceDir) {
|
|
7690
7795
|
return { shouldRetry: false, failureDetail: null, nextPrompt: null };
|
|
7691
7796
|
}
|
|
7692
|
-
const artifactDir =
|
|
7693
|
-
const reviewStatePath =
|
|
7694
|
-
const reviewFeedbackPath =
|
|
7695
|
-
const reviewStatusPath =
|
|
7696
|
-
const failedApproachesPath =
|
|
7697
|
-
const validationSummaryPath =
|
|
7797
|
+
const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
|
|
7798
|
+
const reviewStatePath = resolve22(artifactDir, "review-state.json");
|
|
7799
|
+
const reviewFeedbackPath = resolve22(artifactDir, "review-feedback.md");
|
|
7800
|
+
const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
|
|
7801
|
+
const failedApproachesPath = resolve22(input.workspaceDir, ".rig", "state", "failed_approaches.md");
|
|
7802
|
+
const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
|
|
7698
7803
|
const reviewState = readJsonFile3(reviewStatePath, null);
|
|
7699
7804
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
7700
7805
|
const reviewRejected = isTaskRunReviewRejected(reviewState);
|
|
@@ -7749,11 +7854,11 @@ function summarizeTaskRunReviewFailure(reviewState) {
|
|
|
7749
7854
|
return "Completion verification rejected the task. Read review-feedback.md for required fixes.";
|
|
7750
7855
|
}
|
|
7751
7856
|
function readTaskRunReviewStatus(reviewStatusPath) {
|
|
7752
|
-
if (!
|
|
7857
|
+
if (!existsSync13(reviewStatusPath)) {
|
|
7753
7858
|
return null;
|
|
7754
7859
|
}
|
|
7755
7860
|
try {
|
|
7756
|
-
const status =
|
|
7861
|
+
const status = readFileSync11(reviewStatusPath, "utf8").trim().toUpperCase();
|
|
7757
7862
|
return status === "APPROVED" || status === "REJECTED" ? status : null;
|
|
7758
7863
|
} catch {
|
|
7759
7864
|
return null;
|
|
@@ -7837,7 +7942,7 @@ function stringArrayField(record, key) {
|
|
|
7837
7942
|
async function executeRigOwnedTaskRun(context, input) {
|
|
7838
7943
|
const runtimeTaskId = input.taskId?.trim() || `adhoc-${input.runId}`;
|
|
7839
7944
|
const sourceTask = readRunSourceTaskContract(context.projectRoot, input.runId, input.taskId);
|
|
7840
|
-
|
|
7945
|
+
let prompt = buildRunPrompt({
|
|
7841
7946
|
projectRoot: context.projectRoot,
|
|
7842
7947
|
taskId: input.taskId,
|
|
7843
7948
|
fallbackTitle: input.title,
|
|
@@ -7937,7 +8042,22 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
7937
8042
|
const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
|
|
7938
8043
|
const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
|
|
7939
8044
|
const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
|
|
7940
|
-
|
|
8045
|
+
const planningArtifactPath = resolve22("artifacts", runtimeTaskId, "implementation-plan.md");
|
|
8046
|
+
const persistedPlanning = {
|
|
8047
|
+
...planningClassification,
|
|
8048
|
+
classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
|
|
8049
|
+
artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
|
|
8050
|
+
classifiedAt: new Date().toISOString()
|
|
8051
|
+
};
|
|
8052
|
+
mkdirSync8(resolve22(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
|
|
8053
|
+
writeFileSync6(resolve22(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
|
|
8054
|
+
`, "utf8");
|
|
8055
|
+
patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
|
|
8056
|
+
prompt = `${prompt}
|
|
8057
|
+
|
|
8058
|
+
Rig planning classification:
|
|
8059
|
+
${JSON.stringify(persistedPlanning, null, 2)}
|
|
8060
|
+
${planningClassification.planningRequired ? `Before implementing, write a concise implementation plan to ${planningArtifactPath}. Treat that plan artifact as required acceptance evidence for the Plan stage.` : "Planning is not required for this run; briefly state why before implementation."}`;
|
|
7941
8061
|
if (input.runtimeAdapter === "pi") {
|
|
7942
8062
|
for (const stage of ["Connect", "GitHub/task sync", "Prepare workspace", "Launch Pi", "Plan", "Implement"]) {
|
|
7943
8063
|
appendPiStageLog({
|
|
@@ -8004,6 +8124,7 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
8004
8124
|
...sourceTask ? { RIG_SOURCE_TASK_JSON: JSON.stringify(sourceTask) } : {}
|
|
8005
8125
|
};
|
|
8006
8126
|
Object.assign(childEnv, buildTaskRunReviewEnv(automationConfig));
|
|
8127
|
+
Object.assign(childEnv, buildDirtyBaselineHandshakeEnv({ projectRoot: context.projectRoot, runId: input.runId, baselineMode: input.baselineMode }));
|
|
8007
8128
|
const automationLimits = resolveTaskRunAutomationLimits(automationConfig);
|
|
8008
8129
|
const maxAttempts = automationLimits.maxValidationAttempts;
|
|
8009
8130
|
const promoteToValidating = (detail) => {
|
|
@@ -8058,22 +8179,29 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
8058
8179
|
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
8059
8180
|
status: "running",
|
|
8060
8181
|
worktreePath: latestRuntimeWorkspace,
|
|
8061
|
-
artifactRoot: latestRuntimeWorkspace && input.taskId ?
|
|
8182
|
+
artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve22(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
|
|
8062
8183
|
logRoot: latestLogsDir,
|
|
8063
|
-
sessionPath: latestSessionDir ?
|
|
8064
|
-
sessionLogPath: latestLogsDir ?
|
|
8184
|
+
sessionPath: latestSessionDir ? resolve22(latestSessionDir, "session.json") : null,
|
|
8185
|
+
sessionLogPath: latestLogsDir ? resolve22(latestLogsDir, "agent-stdout.log") : null,
|
|
8065
8186
|
branch: runtimeId
|
|
8066
8187
|
});
|
|
8067
8188
|
if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
|
|
8068
8189
|
dirtyBaselineApplied = true;
|
|
8069
8190
|
const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
|
|
8191
|
+
const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
|
|
8192
|
+
if (readyFile) {
|
|
8193
|
+
mkdirSync8(resolve22(readyFile, ".."), { recursive: true });
|
|
8194
|
+
writeFileSync6(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
|
|
8195
|
+
`, "utf8");
|
|
8196
|
+
}
|
|
8070
8197
|
appendRunLog(context.projectRoot, input.runId, {
|
|
8071
8198
|
id: `log:${input.runId}:dirty-baseline`,
|
|
8072
8199
|
title: "Dirty baseline snapshot",
|
|
8073
8200
|
detail: dirty.detail,
|
|
8074
8201
|
tone: dirty.applied ? "tool" : "info",
|
|
8075
8202
|
status: dirty.applied ? "completed" : "skipped",
|
|
8076
|
-
createdAt: new Date().toISOString()
|
|
8203
|
+
createdAt: new Date().toISOString(),
|
|
8204
|
+
payload: readyFile ? { readyFile } : undefined
|
|
8077
8205
|
});
|
|
8078
8206
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Dirty baseline snapshot" });
|
|
8079
8207
|
}
|
|
@@ -8340,7 +8468,7 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
8340
8468
|
let acceptedArtifactObservedAt = null;
|
|
8341
8469
|
let acceptedArtifactPollTimer = null;
|
|
8342
8470
|
let acceptedArtifactKillTimer = null;
|
|
8343
|
-
const attemptExit = await new Promise((
|
|
8471
|
+
const attemptExit = await new Promise((resolve23) => {
|
|
8344
8472
|
let settled = false;
|
|
8345
8473
|
const settle = (result) => {
|
|
8346
8474
|
if (settled)
|
|
@@ -8348,7 +8476,7 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
8348
8476
|
settled = true;
|
|
8349
8477
|
if (acceptedArtifactPollTimer)
|
|
8350
8478
|
clearInterval(acceptedArtifactPollTimer);
|
|
8351
|
-
|
|
8479
|
+
resolve23(result);
|
|
8352
8480
|
};
|
|
8353
8481
|
const pollAcceptedArtifacts = () => {
|
|
8354
8482
|
const artifactState = readTaskRunAcceptedArtifactState({
|
|
@@ -8545,6 +8673,29 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
8545
8673
|
});
|
|
8546
8674
|
throw new CliError2(terminalFailureDetail, exit.code ?? 1);
|
|
8547
8675
|
}
|
|
8676
|
+
if (planningClassification.planningRequired) {
|
|
8677
|
+
const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
|
|
8678
|
+
const expectedPlanPath = resolve22(planWorkspace, planningArtifactPath);
|
|
8679
|
+
if (!existsSync13(expectedPlanPath)) {
|
|
8680
|
+
const failedAt = new Date().toISOString();
|
|
8681
|
+
const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
|
|
8682
|
+
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
8683
|
+
status: "needs_attention",
|
|
8684
|
+
completedAt: failedAt,
|
|
8685
|
+
errorText: failureDetail
|
|
8686
|
+
});
|
|
8687
|
+
appendRunLog(context.projectRoot, input.runId, {
|
|
8688
|
+
id: `log:${input.runId}:plan-artifact-missing`,
|
|
8689
|
+
title: "Required plan artifact missing",
|
|
8690
|
+
detail: failureDetail,
|
|
8691
|
+
tone: "error",
|
|
8692
|
+
status: "needs_attention",
|
|
8693
|
+
createdAt: failedAt
|
|
8694
|
+
});
|
|
8695
|
+
emitServerRunEvent({ type: "failed", runId: input.runId, error: failureDetail });
|
|
8696
|
+
throw new CliError2(failureDetail, 1);
|
|
8697
|
+
}
|
|
8698
|
+
}
|
|
8548
8699
|
const runPiPrFeedbackFix = async (message2) => {
|
|
8549
8700
|
appendPiStageLog({
|
|
8550
8701
|
projectRoot: context.projectRoot,
|
|
@@ -8602,9 +8753,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
8602
8753
|
});
|
|
8603
8754
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
|
|
8604
8755
|
});
|
|
8605
|
-
const exitCode = await new Promise((
|
|
8606
|
-
child.once("error", () =>
|
|
8607
|
-
child.once("close", (code) =>
|
|
8756
|
+
const exitCode = await new Promise((resolve23) => {
|
|
8757
|
+
child.once("error", () => resolve23(1));
|
|
8758
|
+
child.once("close", (code) => resolve23(code ?? 1));
|
|
8608
8759
|
});
|
|
8609
8760
|
if (exitCode !== 0) {
|
|
8610
8761
|
throw new Error(`Pi PR feedback fix failed with exit code ${exitCode}.`);
|
|
@@ -8723,8 +8874,8 @@ async function executeTest(context, args) {
|
|
|
8723
8874
|
}
|
|
8724
8875
|
|
|
8725
8876
|
// packages/cli/src/commands/setup.ts
|
|
8726
|
-
import { existsSync as
|
|
8727
|
-
import { resolve as
|
|
8877
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync9, readdirSync as readdirSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
8878
|
+
import { resolve as resolve23 } from "path";
|
|
8728
8879
|
import { createPluginHost } from "@rig/core";
|
|
8729
8880
|
import {
|
|
8730
8881
|
isSupportedBunVersion as isSupportedBunVersion2,
|
|
@@ -8787,9 +8938,9 @@ function runSetupInit(projectRoot) {
|
|
|
8787
8938
|
mkdirSync9(stateDir, { recursive: true });
|
|
8788
8939
|
mkdirSync9(logsDir, { recursive: true });
|
|
8789
8940
|
mkdirSync9(artifactsDir, { recursive: true });
|
|
8790
|
-
const failuresPath =
|
|
8791
|
-
if (!
|
|
8792
|
-
|
|
8941
|
+
const failuresPath = resolve23(stateDir, "failed_approaches.md");
|
|
8942
|
+
if (!existsSync14(failuresPath)) {
|
|
8943
|
+
writeFileSync7(failuresPath, `# Failed Approaches
|
|
8793
8944
|
|
|
8794
8945
|
`, "utf-8");
|
|
8795
8946
|
}
|
|
@@ -8806,18 +8957,18 @@ async function runSetupCheck(projectRoot) {
|
|
|
8806
8957
|
}
|
|
8807
8958
|
async function runSetupPreflight(projectRoot) {
|
|
8808
8959
|
await runSetupCheck(projectRoot);
|
|
8809
|
-
const validationRoot =
|
|
8810
|
-
if (
|
|
8960
|
+
const validationRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
8961
|
+
if (existsSync14(validationRoot)) {
|
|
8811
8962
|
const validators = readdirSync2(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
8812
8963
|
for (const validator of validators) {
|
|
8813
|
-
const script =
|
|
8814
|
-
if (
|
|
8964
|
+
const script = resolve23(validationRoot, validator.name, "validate.sh");
|
|
8965
|
+
if (existsSync14(script)) {
|
|
8815
8966
|
console.log(`OK: validator script ${script}`);
|
|
8816
8967
|
}
|
|
8817
8968
|
}
|
|
8818
8969
|
}
|
|
8819
|
-
const hooksRoot =
|
|
8820
|
-
if (
|
|
8970
|
+
const hooksRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
|
|
8971
|
+
if (existsSync14(hooksRoot)) {
|
|
8821
8972
|
const hooks = readdirSync2(hooksRoot).filter((name) => name.endsWith(".sh"));
|
|
8822
8973
|
for (const hook of hooks) {
|
|
8823
8974
|
console.log(`OK: hook ${hook}`);
|
|
@@ -9211,8 +9362,8 @@ var __testOnly = {
|
|
|
9211
9362
|
validateRequiredBugPromptValue
|
|
9212
9363
|
};
|
|
9213
9364
|
// packages/cli/src/launcher.ts
|
|
9214
|
-
import { existsSync as
|
|
9215
|
-
import { resolve as
|
|
9365
|
+
import { existsSync as existsSync15 } from "fs";
|
|
9366
|
+
import { resolve as resolve24 } from "path";
|
|
9216
9367
|
import { loadDotEnvSecrets } from "@rig/runtime/baked-secrets";
|
|
9217
9368
|
import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME, resolveNearestRigProjectRoot } from "@rig/runtime/layout";
|
|
9218
9369
|
function parsePolicyMode(value) {
|
|
@@ -9225,7 +9376,7 @@ function parsePolicyMode(value) {
|
|
|
9225
9376
|
throw new Error(`Invalid --policy-mode value: ${value}. Use off|observe|enforce.`);
|
|
9226
9377
|
}
|
|
9227
9378
|
function hasRigProjectMarker(candidate) {
|
|
9228
|
-
return
|
|
9379
|
+
return existsSync15(resolve24(candidate, RIG_DEFINITION_DIRNAME)) || existsSync15(resolve24(candidate, RIG_STATE_DIRNAME)) || existsSync15(resolve24(candidate, "rig.config.ts")) || existsSync15(resolve24(candidate, "rig.config.json"));
|
|
9229
9380
|
}
|
|
9230
9381
|
function resolveProjectRoot({
|
|
9231
9382
|
envProjectRoot,
|
|
@@ -9234,17 +9385,17 @@ function resolveProjectRoot({
|
|
|
9234
9385
|
cwd = process.cwd()
|
|
9235
9386
|
}) {
|
|
9236
9387
|
if (envProjectRoot) {
|
|
9237
|
-
return
|
|
9388
|
+
return resolve24(cwd, envProjectRoot);
|
|
9238
9389
|
}
|
|
9239
9390
|
const fallbackImportDir = importDir ?? cwd;
|
|
9240
|
-
const candidates = [cwd,
|
|
9391
|
+
const candidates = [cwd, resolve24(execPath, "..", ".."), resolve24(fallbackImportDir, "..")];
|
|
9241
9392
|
for (const candidate of candidates) {
|
|
9242
9393
|
const nearest = resolveNearestRigProjectRoot(candidate);
|
|
9243
9394
|
if (hasRigProjectMarker(nearest)) {
|
|
9244
9395
|
return nearest;
|
|
9245
9396
|
}
|
|
9246
9397
|
}
|
|
9247
|
-
return
|
|
9398
|
+
return resolve24(cwd);
|
|
9248
9399
|
}
|
|
9249
9400
|
function normalizeCliErrorCode(message2, isCliError) {
|
|
9250
9401
|
if (message2.startsWith("Invalid --policy-mode value:")) {
|
|
@@ -9311,7 +9462,7 @@ async function runRigCli(module, options = {}) {
|
|
|
9311
9462
|
runId: context.runId,
|
|
9312
9463
|
outcome,
|
|
9313
9464
|
eventsFile: context.eventBus.getEventsFile(),
|
|
9314
|
-
policyFile:
|
|
9465
|
+
policyFile: resolve24(projectRoot, "rig", "policy", "policy.json"),
|
|
9315
9466
|
policyMode: context.policyMode ?? policyMode ?? module.loadPolicy(projectRoot).mode
|
|
9316
9467
|
}, null, 2));
|
|
9317
9468
|
}
|