@h-rig/cli 0.0.6-alpha.34 → 0.0.6-alpha.35
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 +426 -231
- package/dist/src/commands/_help-catalog.js +14 -0
- package/dist/src/commands/pi.js +168 -0
- package/dist/src/commands/run.js +27 -0
- package/dist/src/commands/task.js +14 -0
- package/dist/src/commands.js +418 -223
- package/dist/src/index.js +426 -231
- package/package.json +6 -6
package/dist/src/commands.js
CHANGED
|
@@ -337,9 +337,9 @@ var init_plugin = __esm(() => {
|
|
|
337
337
|
// packages/cli/src/commands.ts
|
|
338
338
|
init_runner();
|
|
339
339
|
import {
|
|
340
|
-
existsSync as
|
|
340
|
+
existsSync as existsSync15
|
|
341
341
|
} from "fs";
|
|
342
|
-
import { resolve as
|
|
342
|
+
import { resolve as resolve24 } from "path";
|
|
343
343
|
import { readBuildConfig } from "@rig/runtime/build-time-config";
|
|
344
344
|
|
|
345
345
|
// packages/cli/src/commands/browser.ts
|
|
@@ -2450,6 +2450,157 @@ async function executeHarness(context, args) {
|
|
|
2450
2450
|
// packages/cli/src/commands.ts
|
|
2451
2451
|
init_plugin();
|
|
2452
2452
|
|
|
2453
|
+
// packages/cli/src/commands/pi.ts
|
|
2454
|
+
init_runner();
|
|
2455
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
2456
|
+
import { homedir as homedir2 } from "os";
|
|
2457
|
+
import { dirname, resolve as resolve8 } from "path";
|
|
2458
|
+
function settingsPath(root) {
|
|
2459
|
+
return resolve8(root, ".pi", "settings.json");
|
|
2460
|
+
}
|
|
2461
|
+
function userSettingsPath() {
|
|
2462
|
+
return resolve8(homedir2(), ".pi", "agent", "settings.json");
|
|
2463
|
+
}
|
|
2464
|
+
function readJson(path, fallback) {
|
|
2465
|
+
if (!existsSync4(path))
|
|
2466
|
+
return fallback;
|
|
2467
|
+
try {
|
|
2468
|
+
return JSON.parse(readFileSync2(path, "utf-8"));
|
|
2469
|
+
} catch {
|
|
2470
|
+
return fallback;
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
function packageKey(entry) {
|
|
2474
|
+
if (typeof entry === "string")
|
|
2475
|
+
return entry;
|
|
2476
|
+
if (entry && typeof entry === "object" && typeof entry.source === "string") {
|
|
2477
|
+
return entry.source;
|
|
2478
|
+
}
|
|
2479
|
+
return JSON.stringify(entry);
|
|
2480
|
+
}
|
|
2481
|
+
function writeSettings(path, settings) {
|
|
2482
|
+
mkdirSync4(dirname(path), { recursive: true });
|
|
2483
|
+
writeFileSync3(path, `${JSON.stringify(settings, null, 2)}
|
|
2484
|
+
`, "utf-8");
|
|
2485
|
+
}
|
|
2486
|
+
async function searchNpmForPiExtensions(term) {
|
|
2487
|
+
const query = encodeURIComponent(term ? `${term} pi extension` : "pi extension");
|
|
2488
|
+
const url = `https://registry.npmjs.org/-/v1/search?text=${query}&size=20`;
|
|
2489
|
+
const response = await fetch(url);
|
|
2490
|
+
if (!response.ok) {
|
|
2491
|
+
throw new CliError2(`npm registry search failed (${response.status}).`, 2);
|
|
2492
|
+
}
|
|
2493
|
+
const payload = await response.json();
|
|
2494
|
+
const results = [];
|
|
2495
|
+
for (const entry of payload.objects ?? []) {
|
|
2496
|
+
const pkg = entry.package;
|
|
2497
|
+
if (!pkg?.name)
|
|
2498
|
+
continue;
|
|
2499
|
+
const keywords = (pkg.keywords ?? []).map((k) => k.toLowerCase());
|
|
2500
|
+
const piLike = pkg.name.startsWith("pi-") || pkg.name.includes("-pi") || keywords.includes("pi") || keywords.includes("pi-extension") || (pkg.description ?? "").toLowerCase().includes("pi extension") || (pkg.description ?? "").toLowerCase().includes("pi coding agent");
|
|
2501
|
+
if (!piLike)
|
|
2502
|
+
continue;
|
|
2503
|
+
results.push({ name: pkg.name, version: pkg.version ?? "", description: pkg.description ?? "" });
|
|
2504
|
+
}
|
|
2505
|
+
return results;
|
|
2506
|
+
}
|
|
2507
|
+
async function executePi(context, args) {
|
|
2508
|
+
const [command = "list", ...rest] = args;
|
|
2509
|
+
const projectSettingsPath = settingsPath(context.projectRoot);
|
|
2510
|
+
const managedRecordPath = resolve8(context.projectRoot, ".rig", "state", "pi-managed-packages.json");
|
|
2511
|
+
switch (command) {
|
|
2512
|
+
case "list": {
|
|
2513
|
+
requireNoExtraArgs(rest, "rig pi list");
|
|
2514
|
+
const project = readJson(projectSettingsPath, {});
|
|
2515
|
+
const managed = new Set(readJson(managedRecordPath, []));
|
|
2516
|
+
const user = readJson(userSettingsPath(), {});
|
|
2517
|
+
const projectPackages = (Array.isArray(project.packages) ? project.packages : []).map((entry) => ({
|
|
2518
|
+
source: packageKey(entry),
|
|
2519
|
+
managedByRigConfig: managed.has(packageKey(entry))
|
|
2520
|
+
}));
|
|
2521
|
+
const userPackages = (Array.isArray(user.packages) ? user.packages : []).map(packageKey);
|
|
2522
|
+
if (context.outputMode === "text") {
|
|
2523
|
+
console.log("Project Pi packages (.pi/settings.json):");
|
|
2524
|
+
if (projectPackages.length === 0)
|
|
2525
|
+
console.log(" (none)");
|
|
2526
|
+
for (const pkg of projectPackages) {
|
|
2527
|
+
console.log(` ${pkg.source}${pkg.managedByRigConfig ? " [from rig.config runtime.pi.packages]" : ""}`);
|
|
2528
|
+
}
|
|
2529
|
+
console.log("User Pi packages (~/.pi/agent/settings.json):");
|
|
2530
|
+
if (userPackages.length === 0)
|
|
2531
|
+
console.log(" (none)");
|
|
2532
|
+
for (const pkg of userPackages)
|
|
2533
|
+
console.log(` ${pkg}`);
|
|
2534
|
+
console.log("Add more: `rig pi add <npm-package>` \xB7 discover: `rig pi search <term>`");
|
|
2535
|
+
}
|
|
2536
|
+
return { ok: true, group: "pi", command, details: { projectPackages, userPackages } };
|
|
2537
|
+
}
|
|
2538
|
+
case "add": {
|
|
2539
|
+
const [source, ...extra] = rest;
|
|
2540
|
+
requireNoExtraArgs(extra, "rig pi add <package-source>");
|
|
2541
|
+
if (!source) {
|
|
2542
|
+
throw new CliError2("Usage: rig pi add <package-source> (npm name, name@version, or git URL)", 2);
|
|
2543
|
+
}
|
|
2544
|
+
const settings = readJson(projectSettingsPath, {});
|
|
2545
|
+
const packages = Array.isArray(settings.packages) ? settings.packages : [];
|
|
2546
|
+
if (packages.some((entry) => packageKey(entry) === source)) {
|
|
2547
|
+
throw new CliError2(`"${source}" is already in ${projectSettingsPath}.`, 2);
|
|
2548
|
+
}
|
|
2549
|
+
writeSettings(projectSettingsPath, { ...settings, packages: [...packages, source] });
|
|
2550
|
+
if (context.outputMode === "text") {
|
|
2551
|
+
console.log(`Added ${source} to ${projectSettingsPath}.`);
|
|
2552
|
+
console.log("Pi installs missing packages automatically at the next session start (local and worker).");
|
|
2553
|
+
}
|
|
2554
|
+
return { ok: true, group: "pi", command, details: { source, settingsPath: projectSettingsPath } };
|
|
2555
|
+
}
|
|
2556
|
+
case "remove": {
|
|
2557
|
+
const [source, ...extra] = rest;
|
|
2558
|
+
requireNoExtraArgs(extra, "rig pi remove <package-source>");
|
|
2559
|
+
if (!source) {
|
|
2560
|
+
throw new CliError2("Usage: rig pi remove <package-source>", 2);
|
|
2561
|
+
}
|
|
2562
|
+
const managed = new Set(readJson(managedRecordPath, []));
|
|
2563
|
+
if (managed.has(source)) {
|
|
2564
|
+
throw new CliError2(`"${source}" is managed by rig.config.ts (runtime.pi.packages); remove it there instead.`, 2);
|
|
2565
|
+
}
|
|
2566
|
+
const settings = readJson(projectSettingsPath, {});
|
|
2567
|
+
const packages = Array.isArray(settings.packages) ? settings.packages : [];
|
|
2568
|
+
const next = packages.filter((entry) => packageKey(entry) !== source);
|
|
2569
|
+
if (next.length === packages.length) {
|
|
2570
|
+
throw new CliError2(`"${source}" is not in ${projectSettingsPath}.`, 2);
|
|
2571
|
+
}
|
|
2572
|
+
const nextSettings = { ...settings };
|
|
2573
|
+
if (next.length > 0)
|
|
2574
|
+
nextSettings.packages = next;
|
|
2575
|
+
else
|
|
2576
|
+
delete nextSettings.packages;
|
|
2577
|
+
writeSettings(projectSettingsPath, nextSettings);
|
|
2578
|
+
if (context.outputMode === "text") {
|
|
2579
|
+
console.log(`Removed ${source} from ${projectSettingsPath}.`);
|
|
2580
|
+
}
|
|
2581
|
+
return { ok: true, group: "pi", command, details: { source } };
|
|
2582
|
+
}
|
|
2583
|
+
case "search": {
|
|
2584
|
+
const term = rest.join(" ").trim();
|
|
2585
|
+
const results = await searchNpmForPiExtensions(term);
|
|
2586
|
+
if (context.outputMode === "text") {
|
|
2587
|
+
if (results.length === 0) {
|
|
2588
|
+
console.log(`No Pi extension packages found on npm${term ? ` for "${term}"` : ""}.`);
|
|
2589
|
+
} else {
|
|
2590
|
+
console.log(`Pi extension packages on npm${term ? ` matching "${term}"` : ""}:`);
|
|
2591
|
+
for (const pkg of results) {
|
|
2592
|
+
console.log(` ${pkg.name}@${pkg.version} ${pkg.description.slice(0, 80)}`);
|
|
2593
|
+
}
|
|
2594
|
+
console.log("Install one: `rig pi add <name>`");
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
return { ok: true, group: "pi", command, details: { term, results } };
|
|
2598
|
+
}
|
|
2599
|
+
default:
|
|
2600
|
+
throw new CliError2(`Unknown pi command: ${command}. Use list|add|remove|search.`);
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
|
|
2453
2604
|
// packages/cli/src/commands/queue.ts
|
|
2454
2605
|
init_runner();
|
|
2455
2606
|
init__parsers();
|
|
@@ -2461,33 +2612,33 @@ import { ensureProjectMainFreshBeforeRun } from "@rig/runtime/control-plane/proj
|
|
|
2461
2612
|
|
|
2462
2613
|
// packages/cli/src/commands/_connection-state.ts
|
|
2463
2614
|
init_runner();
|
|
2464
|
-
import { existsSync as
|
|
2465
|
-
import { homedir as
|
|
2466
|
-
import { dirname, resolve as
|
|
2615
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync3, writeFileSync as writeFileSync4 } from "fs";
|
|
2616
|
+
import { homedir as homedir3 } from "os";
|
|
2617
|
+
import { dirname as dirname2, resolve as resolve9 } from "path";
|
|
2467
2618
|
function resolveGlobalConnectionsPath(env = process.env) {
|
|
2468
2619
|
const explicit = env.RIG_CONNECTIONS_FILE?.trim();
|
|
2469
2620
|
if (explicit)
|
|
2470
|
-
return
|
|
2621
|
+
return resolve9(explicit);
|
|
2471
2622
|
const stateDir = env.RIG_GLOBAL_STATE_DIR?.trim();
|
|
2472
2623
|
if (stateDir)
|
|
2473
|
-
return
|
|
2474
|
-
return
|
|
2624
|
+
return resolve9(stateDir, "connections.json");
|
|
2625
|
+
return resolve9(homedir3(), ".rig", "connections.json");
|
|
2475
2626
|
}
|
|
2476
2627
|
function resolveRepoConnectionPath(projectRoot) {
|
|
2477
|
-
return
|
|
2628
|
+
return resolve9(projectRoot, ".rig", "state", "connection.json");
|
|
2478
2629
|
}
|
|
2479
2630
|
function readJsonFile2(path) {
|
|
2480
|
-
if (!
|
|
2631
|
+
if (!existsSync5(path))
|
|
2481
2632
|
return null;
|
|
2482
2633
|
try {
|
|
2483
|
-
return JSON.parse(
|
|
2634
|
+
return JSON.parse(readFileSync3(path, "utf8"));
|
|
2484
2635
|
} catch (error) {
|
|
2485
2636
|
throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
|
|
2486
2637
|
}
|
|
2487
2638
|
}
|
|
2488
2639
|
function writeJsonFile2(path, value) {
|
|
2489
|
-
|
|
2490
|
-
|
|
2640
|
+
mkdirSync5(dirname2(path), { recursive: true });
|
|
2641
|
+
writeFileSync4(path, `${JSON.stringify(value, null, 2)}
|
|
2491
2642
|
`, "utf8");
|
|
2492
2643
|
}
|
|
2493
2644
|
function normalizeConnection(value) {
|
|
@@ -2564,8 +2715,8 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
2564
2715
|
|
|
2565
2716
|
// packages/cli/src/commands/_server-client.ts
|
|
2566
2717
|
init_runner();
|
|
2567
|
-
import { existsSync as
|
|
2568
|
-
import { resolve as
|
|
2718
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
2719
|
+
import { resolve as resolve10 } from "path";
|
|
2569
2720
|
import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
|
|
2570
2721
|
var scopedGitHubBearerTokens = new Map;
|
|
2571
2722
|
function cleanToken(value) {
|
|
@@ -2573,22 +2724,22 @@ function cleanToken(value) {
|
|
|
2573
2724
|
return trimmed ? trimmed : null;
|
|
2574
2725
|
}
|
|
2575
2726
|
function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
|
|
2576
|
-
const scopedKey =
|
|
2727
|
+
const scopedKey = resolve10(projectRoot ?? process.cwd());
|
|
2577
2728
|
scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
|
|
2578
2729
|
}
|
|
2579
2730
|
function readPrivateRemoteSessionToken(projectRoot) {
|
|
2580
|
-
const path =
|
|
2581
|
-
if (!
|
|
2731
|
+
const path = resolve10(projectRoot, ".rig", "state", "github-auth.json");
|
|
2732
|
+
if (!existsSync6(path))
|
|
2582
2733
|
return null;
|
|
2583
2734
|
try {
|
|
2584
|
-
const parsed = JSON.parse(
|
|
2735
|
+
const parsed = JSON.parse(readFileSync4(path, "utf8"));
|
|
2585
2736
|
return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
|
|
2586
2737
|
} catch {
|
|
2587
2738
|
return null;
|
|
2588
2739
|
}
|
|
2589
2740
|
}
|
|
2590
2741
|
function readGitHubBearerTokenForRemote(projectRoot) {
|
|
2591
|
-
const scopedKey =
|
|
2742
|
+
const scopedKey = resolve10(projectRoot);
|
|
2592
2743
|
if (scopedGitHubBearerTokens.has(scopedKey))
|
|
2593
2744
|
return scopedGitHubBearerTokens.get(scopedKey) ?? null;
|
|
2594
2745
|
const privateSession = readPrivateRemoteSessionToken(projectRoot);
|
|
@@ -2730,7 +2881,7 @@ async function registerProjectViaServer(context, input) {
|
|
|
2730
2881
|
return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
|
|
2731
2882
|
}
|
|
2732
2883
|
function sleep(ms) {
|
|
2733
|
-
return new Promise((
|
|
2884
|
+
return new Promise((resolve11) => setTimeout(resolve11, ms));
|
|
2734
2885
|
}
|
|
2735
2886
|
function isRetryableProjectRootSwitchError(error) {
|
|
2736
2887
|
if (!(error instanceof Error))
|
|
@@ -3213,7 +3364,7 @@ async function executeQueue(context, args) {
|
|
|
3213
3364
|
|
|
3214
3365
|
// packages/cli/src/commands/agent.ts
|
|
3215
3366
|
init_runner();
|
|
3216
|
-
import { resolve as
|
|
3367
|
+
import { resolve as resolve12 } from "path";
|
|
3217
3368
|
import {
|
|
3218
3369
|
agentId,
|
|
3219
3370
|
cleanupAgentRuntime,
|
|
@@ -3223,8 +3374,8 @@ import {
|
|
|
3223
3374
|
} from "@rig/runtime/control-plane/runtime/isolation";
|
|
3224
3375
|
|
|
3225
3376
|
// packages/cli/src/commands/_authority-runs.ts
|
|
3226
|
-
import { existsSync as
|
|
3227
|
-
import { resolve as
|
|
3377
|
+
import { existsSync as existsSync7 } from "fs";
|
|
3378
|
+
import { resolve as resolve11 } from "path";
|
|
3228
3379
|
import {
|
|
3229
3380
|
readAuthorityRun,
|
|
3230
3381
|
readJsonlFile as readJsonlFile2,
|
|
@@ -3246,8 +3397,8 @@ function normalizeRuntimeAdapter(value) {
|
|
|
3246
3397
|
return "claude-code";
|
|
3247
3398
|
}
|
|
3248
3399
|
function readLatestBeadRecord(projectRoot, taskId) {
|
|
3249
|
-
const issuesPath =
|
|
3250
|
-
if (!
|
|
3400
|
+
const issuesPath = resolve11(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
|
|
3401
|
+
if (!existsSync7(issuesPath)) {
|
|
3251
3402
|
return null;
|
|
3252
3403
|
}
|
|
3253
3404
|
let latest = null;
|
|
@@ -3315,7 +3466,7 @@ function upsertAgentAuthorityRun(projectRoot, input) {
|
|
|
3315
3466
|
} else if ("errorText" in next) {
|
|
3316
3467
|
delete next.errorText;
|
|
3317
3468
|
}
|
|
3318
|
-
writeJsonFile3(
|
|
3469
|
+
writeJsonFile3(resolve11(resolveAuthorityRunDir(projectRoot, input.runId), "run.json"), next);
|
|
3319
3470
|
return next;
|
|
3320
3471
|
}
|
|
3321
3472
|
|
|
@@ -3437,10 +3588,10 @@ async function executeAgent(context, args) {
|
|
|
3437
3588
|
status: "running",
|
|
3438
3589
|
startedAt: createdAt,
|
|
3439
3590
|
worktreePath: runtime.workspaceDir,
|
|
3440
|
-
artifactRoot:
|
|
3591
|
+
artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
|
|
3441
3592
|
logRoot: runtime.logsDir,
|
|
3442
|
-
sessionPath:
|
|
3443
|
-
sessionLogPath:
|
|
3593
|
+
sessionPath: resolve12(runtime.sessionDir, "session.json"),
|
|
3594
|
+
sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
|
|
3444
3595
|
pid: process.pid
|
|
3445
3596
|
});
|
|
3446
3597
|
const result = await runInAgentRuntime({
|
|
@@ -3460,10 +3611,10 @@ async function executeAgent(context, args) {
|
|
|
3460
3611
|
startedAt: createdAt,
|
|
3461
3612
|
completedAt: failedAt,
|
|
3462
3613
|
worktreePath: runtime.workspaceDir,
|
|
3463
|
-
artifactRoot:
|
|
3614
|
+
artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
|
|
3464
3615
|
logRoot: runtime.logsDir,
|
|
3465
|
-
sessionPath:
|
|
3466
|
-
sessionLogPath:
|
|
3616
|
+
sessionPath: resolve12(runtime.sessionDir, "session.json"),
|
|
3617
|
+
sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
|
|
3467
3618
|
pid: process.pid,
|
|
3468
3619
|
errorText: result.stderr ? result.stderr.trim() : `Agent runtime command failed (${result.exitCode})`
|
|
3469
3620
|
});
|
|
@@ -3480,10 +3631,10 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
|
|
|
3480
3631
|
startedAt: createdAt,
|
|
3481
3632
|
completedAt,
|
|
3482
3633
|
worktreePath: runtime.workspaceDir,
|
|
3483
|
-
artifactRoot:
|
|
3634
|
+
artifactRoot: resolve12(runtime.workspaceDir, "artifacts", taskId),
|
|
3484
3635
|
logRoot: runtime.logsDir,
|
|
3485
|
-
sessionPath:
|
|
3486
|
-
sessionLogPath:
|
|
3636
|
+
sessionPath: resolve12(runtime.sessionDir, "session.json"),
|
|
3637
|
+
sessionLogPath: resolve12(runtime.logsDir, "agent-stdout.log"),
|
|
3487
3638
|
pid: process.pid
|
|
3488
3639
|
});
|
|
3489
3640
|
return {
|
|
@@ -3559,8 +3710,8 @@ init__parsers();
|
|
|
3559
3710
|
import {
|
|
3560
3711
|
chmodSync,
|
|
3561
3712
|
copyFileSync as copyFileSync2,
|
|
3562
|
-
existsSync as
|
|
3563
|
-
mkdirSync as
|
|
3713
|
+
existsSync as existsSync8,
|
|
3714
|
+
mkdirSync as mkdirSync6,
|
|
3564
3715
|
readdirSync,
|
|
3565
3716
|
readlinkSync,
|
|
3566
3717
|
rmSync as rmSync3,
|
|
@@ -3568,8 +3719,8 @@ import {
|
|
|
3568
3719
|
symlinkSync,
|
|
3569
3720
|
unlinkSync
|
|
3570
3721
|
} from "fs";
|
|
3571
|
-
import { homedir as
|
|
3572
|
-
import { resolve as
|
|
3722
|
+
import { homedir as homedir4 } from "os";
|
|
3723
|
+
import { resolve as resolve13 } from "path";
|
|
3573
3724
|
import { buildBinary as buildBinary2 } from "@rig/runtime/control-plane/runtime/isolation";
|
|
3574
3725
|
import {
|
|
3575
3726
|
computeRuntimeImageFingerprint,
|
|
@@ -3588,13 +3739,13 @@ async function runQuietBinaryProbe(binaryPath, args, cwd) {
|
|
|
3588
3739
|
|
|
3589
3740
|
// packages/cli/src/commands/dist.ts
|
|
3590
3741
|
function collectRigValidatorBuildTargets(input) {
|
|
3591
|
-
const validatorsRoot =
|
|
3592
|
-
if (!
|
|
3742
|
+
const validatorsRoot = resolve13(input.hostProjectRoot, "packages/runtime/src/control-plane/validators");
|
|
3743
|
+
if (!existsSync8(validatorsRoot))
|
|
3593
3744
|
return [];
|
|
3594
3745
|
const targets = [];
|
|
3595
3746
|
const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
3596
3747
|
for (const category of categories) {
|
|
3597
|
-
const categoryDir =
|
|
3748
|
+
const categoryDir = resolve13(validatorsRoot, category.name);
|
|
3598
3749
|
for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
|
|
3599
3750
|
if (!entry.isFile() || !entry.name.endsWith(".ts"))
|
|
3600
3751
|
continue;
|
|
@@ -3603,7 +3754,7 @@ function collectRigValidatorBuildTargets(input) {
|
|
|
3603
3754
|
continue;
|
|
3604
3755
|
targets.push({
|
|
3605
3756
|
source: `packages/runtime/src/control-plane/validators/${category.name}/${entry.name}`,
|
|
3606
|
-
dest:
|
|
3757
|
+
dest: resolve13(input.imageDir, `bin/validators/${category.name}-${check}`),
|
|
3607
3758
|
cwd: input.hostProjectRoot
|
|
3608
3759
|
});
|
|
3609
3760
|
}
|
|
@@ -3612,16 +3763,16 @@ function collectRigValidatorBuildTargets(input) {
|
|
|
3612
3763
|
}
|
|
3613
3764
|
async function findLatestDistBinary(projectRoot) {
|
|
3614
3765
|
const distRoot = resolveControlPlaneHostDistDir(projectRoot);
|
|
3615
|
-
if (!
|
|
3766
|
+
if (!existsSync8(distRoot)) {
|
|
3616
3767
|
return null;
|
|
3617
3768
|
}
|
|
3618
3769
|
const entries = readdirSync(distRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory() && entry.name.startsWith("rig-")).map((entry) => ({
|
|
3619
3770
|
name: entry.name,
|
|
3620
|
-
mtimeMs: statSync(
|
|
3771
|
+
mtimeMs: statSync(resolve13(distRoot, entry.name)).mtimeMs
|
|
3621
3772
|
})).sort((a, b) => b.mtimeMs - a.mtimeMs || b.name.localeCompare(a.name));
|
|
3622
3773
|
for (const { name } of entries) {
|
|
3623
|
-
const candidate =
|
|
3624
|
-
if (
|
|
3774
|
+
const candidate = resolve13(distRoot, name, "bin", "rig");
|
|
3775
|
+
if (existsSync8(candidate) && await isRunnableRigBinary(candidate, projectRoot)) {
|
|
3625
3776
|
return candidate;
|
|
3626
3777
|
}
|
|
3627
3778
|
}
|
|
@@ -3633,7 +3784,7 @@ async function isRunnableRigBinary(binaryPath, projectRoot) {
|
|
|
3633
3784
|
async function runDistDoctor(projectRoot) {
|
|
3634
3785
|
const bunPath = Bun.which("bun");
|
|
3635
3786
|
const rigPath = Bun.which("rig");
|
|
3636
|
-
const userBinDir =
|
|
3787
|
+
const userBinDir = resolve13(homedir4(), ".local/bin");
|
|
3637
3788
|
const userBinInPath = (process.env.PATH || "").split(":").filter(Boolean).includes(userBinDir);
|
|
3638
3789
|
let rigRunnable = false;
|
|
3639
3790
|
if (rigPath) {
|
|
@@ -3677,19 +3828,19 @@ async function executeDist(context, args) {
|
|
|
3677
3828
|
requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
|
|
3678
3829
|
const scope = parseInstallScope(scopeResult.value);
|
|
3679
3830
|
const installDir = resolveInstallDir(scope, pathResult.value);
|
|
3680
|
-
|
|
3831
|
+
mkdirSync6(installDir, { recursive: true });
|
|
3681
3832
|
let source = await findLatestDistBinary(context.projectRoot);
|
|
3682
3833
|
let buildDir = null;
|
|
3683
3834
|
if (!source) {
|
|
3684
|
-
buildDir =
|
|
3835
|
+
buildDir = resolve13(resolveControlPlaneHostDistDir(context.projectRoot), `rig-install-${Date.now()}`);
|
|
3685
3836
|
await context.runCommand(["bun", "run", "packages/cli/bin/build-rig-binaries.ts", "--output-dir", buildDir]);
|
|
3686
|
-
source =
|
|
3837
|
+
source = resolve13(buildDir, "bin", "rig");
|
|
3687
3838
|
}
|
|
3688
|
-
if (!
|
|
3839
|
+
if (!existsSync8(source)) {
|
|
3689
3840
|
throw new CliError2(`Unable to locate rig binary at ${source}.`, 2);
|
|
3690
3841
|
}
|
|
3691
|
-
const installedPath =
|
|
3692
|
-
if (
|
|
3842
|
+
const installedPath = resolve13(installDir, "rig");
|
|
3843
|
+
if (existsSync8(installedPath)) {
|
|
3693
3844
|
unlinkSync(installedPath);
|
|
3694
3845
|
}
|
|
3695
3846
|
copyFileSync2(source, installedPath);
|
|
@@ -3731,22 +3882,22 @@ async function executeDist(context, args) {
|
|
|
3731
3882
|
requireNoExtraArgs(rest, "rig dist rebuild-agent");
|
|
3732
3883
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
3733
3884
|
const currentId = computeRuntimeImageId(fp);
|
|
3734
|
-
const imagesDir =
|
|
3735
|
-
|
|
3885
|
+
const imagesDir = resolve13(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
3886
|
+
mkdirSync6(imagesDir, { recursive: true });
|
|
3736
3887
|
let pruned = 0;
|
|
3737
3888
|
for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
|
|
3738
3889
|
if (entry.isDirectory() && entry.name !== currentId) {
|
|
3739
|
-
rmSync3(
|
|
3890
|
+
rmSync3(resolve13(imagesDir, entry.name), { recursive: true, force: true });
|
|
3740
3891
|
pruned++;
|
|
3741
3892
|
}
|
|
3742
3893
|
}
|
|
3743
3894
|
if (pruned > 0 && context.outputMode === "text") {
|
|
3744
3895
|
console.log(`Pruned ${pruned} stale image(s).`);
|
|
3745
3896
|
}
|
|
3746
|
-
const imageDir =
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3897
|
+
const imageDir = resolve13(imagesDir, currentId);
|
|
3898
|
+
mkdirSync6(resolve13(imageDir, "bin/hooks"), { recursive: true });
|
|
3899
|
+
mkdirSync6(resolve13(imageDir, "bin/plugins"), { recursive: true });
|
|
3900
|
+
mkdirSync6(resolve13(imageDir, "bin/validators"), { recursive: true });
|
|
3750
3901
|
const hookNames = [
|
|
3751
3902
|
"scope-guard",
|
|
3752
3903
|
"import-guard",
|
|
@@ -3760,25 +3911,25 @@ async function executeDist(context, args) {
|
|
|
3760
3911
|
];
|
|
3761
3912
|
const targets = [];
|
|
3762
3913
|
const hostProjectRoot = process.env.RIG_HOST_PROJECT_ROOT?.trim() || context.projectRoot;
|
|
3763
|
-
targets.push({ source: "packages/runtime/bin/rig-agent.ts", dest:
|
|
3764
|
-
targets.push({ source: "packages/runtime/bin/rig-agent-dispatch.ts", dest:
|
|
3914
|
+
targets.push({ source: "packages/runtime/bin/rig-agent.ts", dest: resolve13(imageDir, "bin/rig-agent"), cwd: hostProjectRoot });
|
|
3915
|
+
targets.push({ source: "packages/runtime/bin/rig-agent-dispatch.ts", dest: resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "rig-agent"), cwd: hostProjectRoot });
|
|
3765
3916
|
for (const hookName of hookNames) {
|
|
3766
3917
|
const src = `packages/runtime/src/control-plane/hooks/${hookName}.ts`;
|
|
3767
|
-
targets.push({ source: src, dest:
|
|
3768
|
-
targets.push({ source: src, dest:
|
|
3769
|
-
}
|
|
3770
|
-
const pluginsDir =
|
|
3771
|
-
const binPluginsDir =
|
|
3772
|
-
const validatorsRoot =
|
|
3773
|
-
const binValidatorsDir =
|
|
3774
|
-
|
|
3775
|
-
|
|
3776
|
-
if (
|
|
3918
|
+
targets.push({ source: src, dest: resolve13(imageDir, `bin/hooks/${hookName}`), cwd: hostProjectRoot });
|
|
3919
|
+
targets.push({ source: src, dest: resolve13(resolveControlPlaneHostBinDir(context.projectRoot), `hooks/${hookName}`), cwd: hostProjectRoot });
|
|
3920
|
+
}
|
|
3921
|
+
const pluginsDir = resolve13(context.projectRoot, "rig/plugins");
|
|
3922
|
+
const binPluginsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
|
|
3923
|
+
const validatorsRoot = resolve13(hostProjectRoot, "packages/runtime/src/control-plane/validators");
|
|
3924
|
+
const binValidatorsDir = resolve13(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
|
|
3925
|
+
mkdirSync6(binPluginsDir, { recursive: true });
|
|
3926
|
+
mkdirSync6(binValidatorsDir, { recursive: true });
|
|
3927
|
+
if (existsSync8(pluginsDir)) {
|
|
3777
3928
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
3778
3929
|
const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
3779
3930
|
if (!m)
|
|
3780
3931
|
continue;
|
|
3781
|
-
targets.push({ source: `rig/plugins/${entry.name}`, dest:
|
|
3932
|
+
targets.push({ source: `rig/plugins/${entry.name}`, dest: resolve13(imageDir, `bin/plugins/${m[1]}`), cwd: context.projectRoot });
|
|
3782
3933
|
}
|
|
3783
3934
|
}
|
|
3784
3935
|
targets.push(...collectRigValidatorBuildTargets({ contextProjectRoot: context.projectRoot, hostProjectRoot, imageDir }));
|
|
@@ -3789,17 +3940,17 @@ async function executeDist(context, args) {
|
|
|
3789
3940
|
const isValidator = dest.includes("/bin/validators/");
|
|
3790
3941
|
await buildBinary2(source, dest, cwd, isValidator ? { AGENT_BUN_PATH: Bun.which("bun") || "bun" } : { AGENT_PROJECT_ROOT: context.projectRoot });
|
|
3791
3942
|
}
|
|
3792
|
-
if (
|
|
3943
|
+
if (existsSync8(pluginsDir)) {
|
|
3793
3944
|
for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
|
|
3794
3945
|
const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
|
|
3795
3946
|
if (!m)
|
|
3796
3947
|
continue;
|
|
3797
3948
|
const pluginName = m[1];
|
|
3798
|
-
const imageBin =
|
|
3949
|
+
const imageBin = resolve13(imageDir, `bin/plugins/${pluginName}`);
|
|
3799
3950
|
if (!pluginName)
|
|
3800
3951
|
continue;
|
|
3801
|
-
const symlinkPath =
|
|
3802
|
-
if (
|
|
3952
|
+
const symlinkPath = resolve13(binPluginsDir, pluginName);
|
|
3953
|
+
if (existsSync8(imageBin)) {
|
|
3803
3954
|
try {
|
|
3804
3955
|
unlinkSync(symlinkPath);
|
|
3805
3956
|
} catch {}
|
|
@@ -3807,10 +3958,10 @@ async function executeDist(context, args) {
|
|
|
3807
3958
|
}
|
|
3808
3959
|
}
|
|
3809
3960
|
}
|
|
3810
|
-
if (
|
|
3961
|
+
if (existsSync8(validatorsRoot)) {
|
|
3811
3962
|
const categories = readdirSync(validatorsRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
3812
3963
|
for (const category of categories) {
|
|
3813
|
-
const categoryDir =
|
|
3964
|
+
const categoryDir = resolve13(validatorsRoot, category.name);
|
|
3814
3965
|
for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
|
|
3815
3966
|
if (!entry.isFile() || !entry.name.endsWith(".ts"))
|
|
3816
3967
|
continue;
|
|
@@ -3818,9 +3969,9 @@ async function executeDist(context, args) {
|
|
|
3818
3969
|
if (!check || check === "index" || check === "shared")
|
|
3819
3970
|
continue;
|
|
3820
3971
|
const validatorName = `${category.name}-${check}`;
|
|
3821
|
-
const imageBin =
|
|
3822
|
-
const symlinkPath =
|
|
3823
|
-
if (
|
|
3972
|
+
const imageBin = resolve13(imageDir, `bin/validators/${validatorName}`);
|
|
3973
|
+
const symlinkPath = resolve13(binValidatorsDir, validatorName);
|
|
3974
|
+
if (existsSync8(imageBin)) {
|
|
3824
3975
|
try {
|
|
3825
3976
|
unlinkSync(symlinkPath);
|
|
3826
3977
|
} catch {}
|
|
@@ -3829,18 +3980,18 @@ async function executeDist(context, args) {
|
|
|
3829
3980
|
}
|
|
3830
3981
|
}
|
|
3831
3982
|
}
|
|
3832
|
-
const agentsDir =
|
|
3833
|
-
if (
|
|
3983
|
+
const agentsDir = resolve13(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "agents");
|
|
3984
|
+
if (existsSync8(agentsDir)) {
|
|
3834
3985
|
let relinkCount = 0;
|
|
3835
3986
|
for (const agentEntry of readdirSync(agentsDir, { withFileTypes: true })) {
|
|
3836
3987
|
if (!agentEntry.isDirectory())
|
|
3837
3988
|
continue;
|
|
3838
|
-
const agentBinDir =
|
|
3839
|
-
if (!
|
|
3989
|
+
const agentBinDir = resolve13(agentsDir, agentEntry.name, "worktree", ".rig", "bin");
|
|
3990
|
+
if (!existsSync8(agentBinDir))
|
|
3840
3991
|
continue;
|
|
3841
3992
|
const walkDir = (dir) => {
|
|
3842
3993
|
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
3843
|
-
const fullPath =
|
|
3994
|
+
const fullPath = resolve13(dir, entry.name);
|
|
3844
3995
|
if (entry.isDirectory()) {
|
|
3845
3996
|
walkDir(fullPath);
|
|
3846
3997
|
} else if (entry.isSymbolicLink()) {
|
|
@@ -3874,8 +4025,8 @@ async function executeDist(context, args) {
|
|
|
3874
4025
|
|
|
3875
4026
|
// packages/cli/src/commands/inbox.ts
|
|
3876
4027
|
init_runner();
|
|
3877
|
-
import { writeFileSync as
|
|
3878
|
-
import { resolve as
|
|
4028
|
+
import { writeFileSync as writeFileSync5 } from "fs";
|
|
4029
|
+
import { resolve as resolve14 } from "path";
|
|
3879
4030
|
import {
|
|
3880
4031
|
listAuthorityRuns,
|
|
3881
4032
|
readJsonlFile as readJsonlFile3,
|
|
@@ -4277,7 +4428,7 @@ async function listRemoteInboxRecords(context, kind, filters) {
|
|
|
4277
4428
|
function listLocalInboxRecords(context, kind, filters) {
|
|
4278
4429
|
const fileName = kind === "approvals" ? "approvals.jsonl" : "user-input.jsonl";
|
|
4279
4430
|
const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!filters.run || entry.runId === filters.run) && (!filters.task || entry.taskId === filters.task));
|
|
4280
|
-
return runs.flatMap((entry) => readJsonlFile3(
|
|
4431
|
+
return runs.flatMap((entry) => readJsonlFile3(resolve14(resolveAuthorityRunDir2(context.projectRoot, entry.runId), fileName)).map((record) => ({
|
|
4281
4432
|
runId: entry.runId,
|
|
4282
4433
|
taskId: entry.taskId ?? undefined,
|
|
4283
4434
|
record
|
|
@@ -4325,11 +4476,11 @@ async function executeInbox(context, args) {
|
|
|
4325
4476
|
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4326
4477
|
throw new CliError2("Remote approval resolution is not available from this CLI yet; use the server UI/API or switch to local state for direct JSONL edits.", 2);
|
|
4327
4478
|
}
|
|
4328
|
-
const approvalsPath =
|
|
4479
|
+
const approvalsPath = resolve14(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
|
|
4329
4480
|
const approvals = readJsonlFile3(approvalsPath);
|
|
4330
4481
|
const resolvedAt = new Date().toISOString();
|
|
4331
4482
|
const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note: note4.value ?? null, resolvedAt } : entry);
|
|
4332
|
-
|
|
4483
|
+
writeFileSync5(approvalsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
|
|
4333
4484
|
`)}
|
|
4334
4485
|
`, "utf8");
|
|
4335
4486
|
return { ok: true, group: "inbox", command, details: { runId: run.value, requestId: request.value, decision: decision.value } };
|
|
@@ -4381,11 +4532,11 @@ async function executeInbox(context, args) {
|
|
|
4381
4532
|
const [key, ...restValue] = entry.split("=");
|
|
4382
4533
|
return [key, restValue.join("=")];
|
|
4383
4534
|
}));
|
|
4384
|
-
const requestsPath =
|
|
4535
|
+
const requestsPath = resolve14(resolveAuthorityRunDir2(context.projectRoot, run.value), "user-input.jsonl");
|
|
4385
4536
|
const requests = readJsonlFile3(requestsPath);
|
|
4386
4537
|
const resolvedAt = new Date().toISOString();
|
|
4387
4538
|
const next = requests.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", answers: parsedAnswers, respondedAt: resolvedAt, resolvedAt } : entry);
|
|
4388
|
-
|
|
4539
|
+
writeFileSync5(requestsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
|
|
4389
4540
|
`)}
|
|
4390
4541
|
`, "utf8");
|
|
4391
4542
|
return { ok: true, group: "inbox", command, details: { runId: run.value, requestId: request.value, answers: parsedAnswers } };
|
|
@@ -4397,16 +4548,16 @@ async function executeInbox(context, args) {
|
|
|
4397
4548
|
|
|
4398
4549
|
// packages/cli/src/commands/init.ts
|
|
4399
4550
|
init_runner();
|
|
4400
|
-
import { appendFileSync as appendFileSync2, existsSync as
|
|
4551
|
+
import { appendFileSync as appendFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync7, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
|
|
4401
4552
|
import { spawnSync } from "child_process";
|
|
4402
|
-
import { resolve as
|
|
4553
|
+
import { resolve as resolve18 } from "path";
|
|
4403
4554
|
import { buildRigInitConfigSource } from "@rig/core";
|
|
4404
4555
|
import { listGitHubProjects as listGitHubProjectsDirect, resolveProjectStatusField as resolveProjectStatusFieldDirect } from "@rig/server";
|
|
4405
4556
|
|
|
4406
4557
|
// packages/cli/src/commands/_pi-install.ts
|
|
4407
|
-
import { existsSync as
|
|
4408
|
-
import { homedir as
|
|
4409
|
-
import { resolve as
|
|
4558
|
+
import { existsSync as existsSync9, readFileSync as readFileSync5, rmSync as rmSync4 } from "fs";
|
|
4559
|
+
import { homedir as homedir5 } from "os";
|
|
4560
|
+
import { resolve as resolve15 } from "path";
|
|
4410
4561
|
var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
|
|
4411
4562
|
var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
|
|
4412
4563
|
var LEGACY_PI_RIG_MARKER = `// Managed by Rig. Source package: @rig/pi-rig.
|
|
@@ -4422,16 +4573,16 @@ async function defaultCommandRunner(command, options = {}) {
|
|
|
4422
4573
|
return { exitCode, stdout, stderr };
|
|
4423
4574
|
}
|
|
4424
4575
|
function resolvePiRigExtensionPath(homeDir) {
|
|
4425
|
-
return
|
|
4576
|
+
return resolve15(homeDir, ".pi", "agent", "extensions", "pi-rig");
|
|
4426
4577
|
}
|
|
4427
|
-
function resolvePiRigPackageSource(projectRoot, exists =
|
|
4428
|
-
const localPackage =
|
|
4429
|
-
if (exists(
|
|
4578
|
+
function resolvePiRigPackageSource(projectRoot, exists = existsSync9) {
|
|
4579
|
+
const localPackage = resolve15(projectRoot, "packages", "pi-rig");
|
|
4580
|
+
if (exists(resolve15(localPackage, "package.json")))
|
|
4430
4581
|
return localPackage;
|
|
4431
4582
|
return `npm:${PI_RIG_PACKAGE_NAME}`;
|
|
4432
4583
|
}
|
|
4433
4584
|
function resolvePiHomeDir(inputHomeDir) {
|
|
4434
|
-
return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ??
|
|
4585
|
+
return inputHomeDir ?? process.env.RIG_PI_HOME_DIR?.trim() ?? homedir5();
|
|
4435
4586
|
}
|
|
4436
4587
|
function piListContainsPiRig(output) {
|
|
4437
4588
|
return output.split(/\r?\n/).some((line) => {
|
|
@@ -4477,13 +4628,13 @@ async function ensurePiBinaryAvailable(input) {
|
|
|
4477
4628
|
...next.exitCode === 0 ? {} : { error: (next.stderr || next.stdout).trim() || "pi --version failed after install" }
|
|
4478
4629
|
};
|
|
4479
4630
|
}
|
|
4480
|
-
function removeManagedLegacyPiRigBridge(homeDir, exists =
|
|
4631
|
+
function removeManagedLegacyPiRigBridge(homeDir, exists = existsSync9) {
|
|
4481
4632
|
const extensionPath = resolvePiRigExtensionPath(homeDir);
|
|
4482
|
-
const indexPath =
|
|
4633
|
+
const indexPath = resolve15(extensionPath, "index.ts");
|
|
4483
4634
|
if (!exists(indexPath))
|
|
4484
4635
|
return;
|
|
4485
4636
|
try {
|
|
4486
|
-
const content =
|
|
4637
|
+
const content = readFileSync5(indexPath, "utf8");
|
|
4487
4638
|
if (content === LEGACY_PI_RIG_MARKER || content.includes("Managed by Rig. Source package: @rig/pi-rig")) {
|
|
4488
4639
|
rmSync4(extensionPath, { recursive: true, force: true });
|
|
4489
4640
|
}
|
|
@@ -4499,13 +4650,13 @@ async function checkPiRigInstall(input = {}) {
|
|
|
4499
4650
|
piRig: { ok: true, label: "pi-rig global extension", detail: extensionPath }
|
|
4500
4651
|
};
|
|
4501
4652
|
}
|
|
4502
|
-
const exists = input.exists ??
|
|
4653
|
+
const exists = input.exists ?? existsSync9;
|
|
4503
4654
|
const runner = input.commandRunner ?? defaultCommandRunner;
|
|
4504
4655
|
const piResult = await safeRun(runner, ["pi", "--version"]);
|
|
4505
4656
|
const piListResult = piResult.exitCode === 0 ? await safeRun(runner, ["pi", "list"]) : { exitCode: 1, stdout: "", stderr: "" };
|
|
4506
4657
|
const listedPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
|
|
4507
4658
|
${piListResult.stderr}`);
|
|
4508
|
-
const legacyBridge = exists(
|
|
4659
|
+
const legacyBridge = exists(resolve15(extensionPath, "index.ts"));
|
|
4509
4660
|
const hasPiRig = listedPiRig;
|
|
4510
4661
|
return {
|
|
4511
4662
|
extensionPath,
|
|
@@ -4582,7 +4733,7 @@ async function buildPiSetupChecks(input = {}) {
|
|
|
4582
4733
|
|
|
4583
4734
|
// packages/cli/src/commands/_snapshot-upload.ts
|
|
4584
4735
|
import { mkdir, readdir, readFile, writeFile } from "fs/promises";
|
|
4585
|
-
import { dirname as
|
|
4736
|
+
import { dirname as dirname3, resolve as resolve16, relative, sep } from "path";
|
|
4586
4737
|
var SNAPSHOT_ARCHIVE_VERSION = 1;
|
|
4587
4738
|
var SNAPSHOT_ARCHIVE_CONTENT_TYPE = "application/vnd.rig.snapshot+json";
|
|
4588
4739
|
var DEFAULT_EXCLUDED_DIRECTORIES = new Set([
|
|
@@ -4604,15 +4755,15 @@ function assertManifestPath(root, relativePath) {
|
|
|
4604
4755
|
if (!relativePath || relativePath.startsWith("/") || relativePath.includes("\x00")) {
|
|
4605
4756
|
throw new Error(`Invalid snapshot path: ${relativePath}`);
|
|
4606
4757
|
}
|
|
4607
|
-
const resolved =
|
|
4758
|
+
const resolved = resolve16(root, relativePath);
|
|
4608
4759
|
const relativeToRoot = relative(root, resolved);
|
|
4609
|
-
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." ||
|
|
4760
|
+
if (relativeToRoot.startsWith("..") || relativeToRoot === ".." || resolve16(relativeToRoot) === resolved) {
|
|
4610
4761
|
throw new Error(`Snapshot path escapes project root: ${relativePath}`);
|
|
4611
4762
|
}
|
|
4612
4763
|
return resolved;
|
|
4613
4764
|
}
|
|
4614
4765
|
async function buildSnapshotUploadManifest(projectRoot, options = {}) {
|
|
4615
|
-
const root =
|
|
4766
|
+
const root = resolve16(projectRoot);
|
|
4616
4767
|
const excludedDirectories = [...new Set([
|
|
4617
4768
|
...DEFAULT_EXCLUDED_DIRECTORIES,
|
|
4618
4769
|
...options.excludedDirectories ?? []
|
|
@@ -4624,7 +4775,7 @@ async function buildSnapshotUploadManifest(projectRoot, options = {}) {
|
|
|
4624
4775
|
for (const entry of entries) {
|
|
4625
4776
|
if (entry.isDirectory() && excludedSet.has(entry.name))
|
|
4626
4777
|
continue;
|
|
4627
|
-
const fullPath =
|
|
4778
|
+
const fullPath = resolve16(dir, entry.name);
|
|
4628
4779
|
if (entry.isDirectory()) {
|
|
4629
4780
|
await visit(fullPath);
|
|
4630
4781
|
continue;
|
|
@@ -4673,8 +4824,8 @@ async function uploadSnapshotArchiveViaServer(context, input) {
|
|
|
4673
4824
|
|
|
4674
4825
|
// packages/cli/src/commands/_doctor-checks.ts
|
|
4675
4826
|
init_runner();
|
|
4676
|
-
import { existsSync as
|
|
4677
|
-
import { resolve as
|
|
4827
|
+
import { existsSync as existsSync10, readFileSync as readFileSync6 } from "fs";
|
|
4828
|
+
import { resolve as resolve17 } from "path";
|
|
4678
4829
|
import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
|
|
4679
4830
|
init__parsers();
|
|
4680
4831
|
function check(id, label, status, detail, remediation) {
|
|
@@ -4715,11 +4866,11 @@ function repoSlugFromConfig(config) {
|
|
|
4715
4866
|
function loadFallbackConfig(projectRoot) {
|
|
4716
4867
|
const candidates = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
|
|
4717
4868
|
for (const name of candidates) {
|
|
4718
|
-
const path =
|
|
4719
|
-
if (!
|
|
4869
|
+
const path = resolve17(projectRoot, name);
|
|
4870
|
+
if (!existsSync10(path))
|
|
4720
4871
|
continue;
|
|
4721
4872
|
try {
|
|
4722
|
-
const source =
|
|
4873
|
+
const source = readFileSync6(path, "utf8");
|
|
4723
4874
|
if (name.endsWith(".json"))
|
|
4724
4875
|
return JSON.parse(source);
|
|
4725
4876
|
const owner = source.match(/owner\s*:\s*["']([^"']+)["']/)?.[1];
|
|
@@ -4798,7 +4949,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4798
4949
|
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`)."));
|
|
4799
4950
|
const loadedConfig = await loadConfig(projectRoot).catch(() => null);
|
|
4800
4951
|
const config = loadedConfig ?? loadFallbackConfig(projectRoot);
|
|
4801
|
-
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) =>
|
|
4952
|
+
const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync10(resolve17(projectRoot, name)));
|
|
4802
4953
|
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."));
|
|
4803
4954
|
const taskSourceKind = config?.taskSource?.kind;
|
|
4804
4955
|
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."));
|
|
@@ -4917,20 +5068,20 @@ function parseRepoSlug(value) {
|
|
|
4917
5068
|
return { owner: match[1], repo: match[2], slug: `${match[1]}/${match[2]}` };
|
|
4918
5069
|
}
|
|
4919
5070
|
function ensureRigPrivateDirs(projectRoot) {
|
|
4920
|
-
const rigDir =
|
|
4921
|
-
|
|
4922
|
-
|
|
4923
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
4926
|
-
const taskConfigPath =
|
|
4927
|
-
if (!
|
|
4928
|
-
|
|
5071
|
+
const rigDir = resolve18(projectRoot, ".rig");
|
|
5072
|
+
mkdirSync7(resolve18(rigDir, "state"), { recursive: true });
|
|
5073
|
+
mkdirSync7(resolve18(rigDir, "logs"), { recursive: true });
|
|
5074
|
+
mkdirSync7(resolve18(rigDir, "runs"), { recursive: true });
|
|
5075
|
+
mkdirSync7(resolve18(rigDir, "tmp"), { recursive: true });
|
|
5076
|
+
mkdirSync7(resolve18(projectRoot, "artifacts"), { recursive: true });
|
|
5077
|
+
const taskConfigPath = resolve18(rigDir, "task-config.json");
|
|
5078
|
+
if (!existsSync11(taskConfigPath))
|
|
5079
|
+
writeFileSync6(taskConfigPath, `{}
|
|
4929
5080
|
`, "utf-8");
|
|
4930
5081
|
}
|
|
4931
5082
|
function ensureGitignoreEntries(projectRoot) {
|
|
4932
|
-
const path =
|
|
4933
|
-
const existing =
|
|
5083
|
+
const path = resolve18(projectRoot, ".gitignore");
|
|
5084
|
+
const existing = existsSync11(path) ? readFileSync7(path, "utf8") : "";
|
|
4934
5085
|
const entries = [".rig/state/", ".rig/logs/", ".rig/runs/", ".rig/tmp/"];
|
|
4935
5086
|
const missing = entries.filter((entry) => !existing.split(/\r?\n/).includes(entry));
|
|
4936
5087
|
if (missing.length === 0)
|
|
@@ -4943,17 +5094,17 @@ function ensureGitignoreEntries(projectRoot) {
|
|
|
4943
5094
|
`, "utf8");
|
|
4944
5095
|
}
|
|
4945
5096
|
function ensureRigConfigPackageDependencies(projectRoot) {
|
|
4946
|
-
const path =
|
|
4947
|
-
const existing =
|
|
5097
|
+
const path = resolve18(projectRoot, "package.json");
|
|
5098
|
+
const existing = existsSync11(path) ? JSON.parse(readFileSync7(path, "utf8")) : {};
|
|
4948
5099
|
const devDependencies = existing.devDependencies && typeof existing.devDependencies === "object" && !Array.isArray(existing.devDependencies) ? { ...existing.devDependencies } : {};
|
|
4949
5100
|
for (const [name, spec] of Object.entries(RIG_CONFIG_DEV_DEPENDENCIES)) {
|
|
4950
5101
|
devDependencies[name] = spec;
|
|
4951
5102
|
}
|
|
4952
5103
|
const next = {
|
|
4953
|
-
...
|
|
5104
|
+
...existsSync11(path) ? existing : { name: "rig-project", private: true },
|
|
4954
5105
|
devDependencies
|
|
4955
5106
|
};
|
|
4956
|
-
|
|
5107
|
+
writeFileSync6(path, `${JSON.stringify(next, null, 2)}
|
|
4957
5108
|
`, "utf8");
|
|
4958
5109
|
}
|
|
4959
5110
|
function applyGitHubProjectConfig(source, options) {
|
|
@@ -5202,7 +5353,7 @@ async function promptGitHubProjectConfig(context, prompts, repoSlug, githubToken
|
|
|
5202
5353
|
};
|
|
5203
5354
|
}
|
|
5204
5355
|
function sleep2(ms) {
|
|
5205
|
-
return new Promise((
|
|
5356
|
+
return new Promise((resolve19) => setTimeout(resolve19, ms));
|
|
5206
5357
|
}
|
|
5207
5358
|
function positiveIntFromEnv(name, fallback) {
|
|
5208
5359
|
const value = Number.parseInt(process.env[name] ?? "", 10);
|
|
@@ -5231,7 +5382,7 @@ function remoteGitHubAuthMetadata(payload) {
|
|
|
5231
5382
|
};
|
|
5232
5383
|
}
|
|
5233
5384
|
function writeRemoteGitHubAuthState(projectRoot, input) {
|
|
5234
|
-
|
|
5385
|
+
writeFileSync6(resolve18(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
|
|
5235
5386
|
authenticated: true,
|
|
5236
5387
|
source: input.source,
|
|
5237
5388
|
storedOnServer: true,
|
|
@@ -5288,9 +5439,9 @@ async function runControlPlaneInit(context, options) {
|
|
|
5288
5439
|
});
|
|
5289
5440
|
ensureRigPrivateDirs(projectRoot);
|
|
5290
5441
|
ensureGitignoreEntries(projectRoot);
|
|
5291
|
-
const configTsPath =
|
|
5292
|
-
const configJsonPath =
|
|
5293
|
-
const configExists =
|
|
5442
|
+
const configTsPath = resolve18(projectRoot, "rig.config.ts");
|
|
5443
|
+
const configJsonPath = resolve18(projectRoot, "rig.config.json");
|
|
5444
|
+
const configExists = existsSync11(configTsPath) || existsSync11(configJsonPath);
|
|
5294
5445
|
if (!options.privateStateOnly) {
|
|
5295
5446
|
if (configExists && !options.repair) {
|
|
5296
5447
|
if (context.outputMode !== "json")
|
|
@@ -5302,11 +5453,11 @@ async function runControlPlaneInit(context, options) {
|
|
|
5302
5453
|
taskSource: { kind: "github-issues", owner: repo.owner, repo: repo.repo },
|
|
5303
5454
|
useStandardPlugin: true
|
|
5304
5455
|
}), options);
|
|
5305
|
-
|
|
5456
|
+
writeFileSync6(configTsPath, source, "utf-8");
|
|
5306
5457
|
}
|
|
5307
5458
|
ensureRigConfigPackageDependencies(projectRoot);
|
|
5308
5459
|
}
|
|
5309
|
-
|
|
5460
|
+
writeFileSync6(resolve18(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
|
|
5310
5461
|
`, "utf8");
|
|
5311
5462
|
const checkout = checkoutForInit(projectRoot, serverKind, options.remoteCheckout);
|
|
5312
5463
|
let uploadedSnapshot = null;
|
|
@@ -5502,7 +5653,7 @@ function parseInitOptions(args) {
|
|
|
5502
5653
|
async function runInteractiveControlPlaneInit(context, prompts) {
|
|
5503
5654
|
prompts.intro?.("Initialize a Rig control-plane project");
|
|
5504
5655
|
const projectRoot = context.projectRoot;
|
|
5505
|
-
const existingConfig =
|
|
5656
|
+
const existingConfig = existsSync11(resolve18(projectRoot, "rig.config.ts")) || existsSync11(resolve18(projectRoot, "rig.config.json"));
|
|
5506
5657
|
let repair = false;
|
|
5507
5658
|
let privateStateOnly = false;
|
|
5508
5659
|
if (existingConfig) {
|
|
@@ -5805,8 +5956,8 @@ async function executeDoctor(context, args) {
|
|
|
5805
5956
|
|
|
5806
5957
|
// packages/cli/src/commands/_run-driver-helpers.ts
|
|
5807
5958
|
init_runner();
|
|
5808
|
-
import { readFileSync as
|
|
5809
|
-
import { resolve as
|
|
5959
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
5960
|
+
import { resolve as resolve19 } from "path";
|
|
5810
5961
|
import {
|
|
5811
5962
|
appendJsonlRecord as appendJsonlRecord2,
|
|
5812
5963
|
readAuthorityRun as readAuthorityRun2,
|
|
@@ -5826,7 +5977,7 @@ function patchAuthorityRun(projectRoot, runId, patch) {
|
|
|
5826
5977
|
...patch,
|
|
5827
5978
|
updatedAt: new Date().toISOString()
|
|
5828
5979
|
};
|
|
5829
|
-
writeJsonFile4(
|
|
5980
|
+
writeJsonFile4(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), next);
|
|
5830
5981
|
return next;
|
|
5831
5982
|
}
|
|
5832
5983
|
function touchAuthorityRun(projectRoot, runId) {
|
|
@@ -5834,21 +5985,21 @@ function touchAuthorityRun(projectRoot, runId) {
|
|
|
5834
5985
|
if (!current) {
|
|
5835
5986
|
return;
|
|
5836
5987
|
}
|
|
5837
|
-
writeJsonFile4(
|
|
5988
|
+
writeJsonFile4(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "run.json"), {
|
|
5838
5989
|
...current,
|
|
5839
5990
|
updatedAt: new Date().toISOString()
|
|
5840
5991
|
});
|
|
5841
5992
|
}
|
|
5842
5993
|
function appendRunTimeline(projectRoot, runId, value) {
|
|
5843
|
-
appendJsonlRecord2(
|
|
5994
|
+
appendJsonlRecord2(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), value);
|
|
5844
5995
|
touchAuthorityRun(projectRoot, runId);
|
|
5845
5996
|
}
|
|
5846
5997
|
function appendRunLog(projectRoot, runId, value) {
|
|
5847
|
-
appendJsonlRecord2(
|
|
5998
|
+
appendJsonlRecord2(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "logs.jsonl"), value);
|
|
5848
5999
|
touchAuthorityRun(projectRoot, runId);
|
|
5849
6000
|
}
|
|
5850
6001
|
function appendRunAction(projectRoot, runId, value) {
|
|
5851
|
-
appendJsonlRecord2(
|
|
6002
|
+
appendJsonlRecord2(resolve19(resolveAuthorityRunDir3(projectRoot, runId), "timeline.jsonl"), {
|
|
5852
6003
|
id: value.id,
|
|
5853
6004
|
type: "action",
|
|
5854
6005
|
actionType: value.actionType,
|
|
@@ -5919,7 +6070,7 @@ function buildRunPrompt(input) {
|
|
|
5919
6070
|
})();
|
|
5920
6071
|
const scopeText = (() => {
|
|
5921
6072
|
try {
|
|
5922
|
-
const parsed = JSON.parse(
|
|
6073
|
+
const parsed = JSON.parse(readFileSync8(resolveControlPlaneTaskConfigPath(input.projectRoot), "utf8"));
|
|
5923
6074
|
const entry = parsed[input.taskId] ?? {};
|
|
5924
6075
|
const scope = Array.isArray(entry.scope) ? entry.scope.filter((item) => typeof item === "string") : [];
|
|
5925
6076
|
const validation = Array.isArray(entry.validation) ? entry.validation.filter((item) => typeof item === "string") : [];
|
|
@@ -6033,8 +6184,8 @@ function renderSourceScopeValidation(task, validation) {
|
|
|
6033
6184
|
|
|
6034
6185
|
// packages/cli/src/commands/inspect.ts
|
|
6035
6186
|
init_runner();
|
|
6036
|
-
import { existsSync as
|
|
6037
|
-
import { resolve as
|
|
6187
|
+
import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
|
|
6188
|
+
import { resolve as resolve20 } from "path";
|
|
6038
6189
|
import {
|
|
6039
6190
|
listAuthorityRuns as listAuthorityRuns2,
|
|
6040
6191
|
readAuthorityRun as readAuthorityRun3,
|
|
@@ -6055,8 +6206,8 @@ async function executeInspect(context, args) {
|
|
|
6055
6206
|
if (!latestRun) {
|
|
6056
6207
|
throw new CliError2(`No runs found for ${requiredTask}.`);
|
|
6057
6208
|
}
|
|
6058
|
-
const logsPath =
|
|
6059
|
-
if (!
|
|
6209
|
+
const logsPath = resolve20(resolveAuthorityRunDir4(context.projectRoot, latestRun.runId), "logs.jsonl");
|
|
6210
|
+
if (!existsSync12(logsPath)) {
|
|
6060
6211
|
throw new CliError2(`No logs found for run ${latestRun.runId}.`);
|
|
6061
6212
|
}
|
|
6062
6213
|
await context.runCommand(["cat", logsPath]);
|
|
@@ -6066,7 +6217,7 @@ async function executeInspect(context, args) {
|
|
|
6066
6217
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
6067
6218
|
requireNoExtraArgs(remaining, "rig inspect artifacts --task <task-id>");
|
|
6068
6219
|
const requiredTask = requireTask(task, "rig inspect artifacts --task <task-id>");
|
|
6069
|
-
const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) =>
|
|
6220
|
+
const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync12(path));
|
|
6070
6221
|
if (!artifactRoot) {
|
|
6071
6222
|
throw new CliError2(`No artifacts found for ${requiredTask}.`);
|
|
6072
6223
|
}
|
|
@@ -6123,10 +6274,10 @@ async function executeInspect(context, args) {
|
|
|
6123
6274
|
case "failures": {
|
|
6124
6275
|
requireNoExtraArgs(rest, "rig inspect failures");
|
|
6125
6276
|
const failed = resolveHarnessPaths2(context.projectRoot).failedApproachesPath;
|
|
6126
|
-
if (!
|
|
6277
|
+
if (!existsSync12(failed)) {
|
|
6127
6278
|
console.log("No failures recorded.");
|
|
6128
6279
|
} else {
|
|
6129
|
-
process.stdout.write(
|
|
6280
|
+
process.stdout.write(readFileSync9(failed, "utf-8"));
|
|
6130
6281
|
}
|
|
6131
6282
|
return { ok: true, group: "inspect", command };
|
|
6132
6283
|
}
|
|
@@ -6143,11 +6294,11 @@ async function executeInspect(context, args) {
|
|
|
6143
6294
|
return { ok: true, group: "inspect", command };
|
|
6144
6295
|
case "audit": {
|
|
6145
6296
|
requireNoExtraArgs(rest, "rig inspect audit");
|
|
6146
|
-
const auditPath =
|
|
6147
|
-
if (!
|
|
6297
|
+
const auditPath = resolve20(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
|
|
6298
|
+
if (!existsSync12(auditPath)) {
|
|
6148
6299
|
console.log("No audit log found.");
|
|
6149
6300
|
} else {
|
|
6150
|
-
const lines =
|
|
6301
|
+
const lines = readFileSync9(auditPath, "utf-8").split(/\r?\n/).filter(Boolean).slice(-20);
|
|
6151
6302
|
for (const line of lines) {
|
|
6152
6303
|
console.log(line);
|
|
6153
6304
|
}
|
|
@@ -7346,7 +7497,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
7346
7497
|
const buffered = [];
|
|
7347
7498
|
const wsUrl = await buildRunPiEventsWebSocketUrl(options.context, options.runId);
|
|
7348
7499
|
const socket = new WebSocket(wsUrl);
|
|
7349
|
-
const closePromise = new Promise((
|
|
7500
|
+
const closePromise = new Promise((resolve21) => {
|
|
7350
7501
|
socket.onopen = () => {
|
|
7351
7502
|
state.wsConnected = true;
|
|
7352
7503
|
state.status = "live worker Pi WebSocket connected";
|
|
@@ -7371,7 +7522,7 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
7371
7522
|
state.wsConnected = false;
|
|
7372
7523
|
state.status = "worker Pi WebSocket disconnected";
|
|
7373
7524
|
updatePiUi(ctx, state);
|
|
7374
|
-
|
|
7525
|
+
resolve21();
|
|
7375
7526
|
};
|
|
7376
7527
|
});
|
|
7377
7528
|
try {
|
|
@@ -7407,11 +7558,11 @@ async function connectWorkerStream(options, ctx, state) {
|
|
|
7407
7558
|
function createRemoteBashOperations(options, state, excludeFromContext) {
|
|
7408
7559
|
return {
|
|
7409
7560
|
exec(command, _cwd, execOptions) {
|
|
7410
|
-
return new Promise((
|
|
7561
|
+
return new Promise((resolve21, reject) => {
|
|
7411
7562
|
const pending = {
|
|
7412
7563
|
command,
|
|
7413
7564
|
onData: execOptions.onData,
|
|
7414
|
-
resolve:
|
|
7565
|
+
resolve: resolve21,
|
|
7415
7566
|
reject,
|
|
7416
7567
|
sawChunk: false
|
|
7417
7568
|
};
|
|
@@ -8074,6 +8225,33 @@ async function executeRun(context, args) {
|
|
|
8074
8225
|
}
|
|
8075
8226
|
return { ok: true, group: "run", command, details: restarted };
|
|
8076
8227
|
}
|
|
8228
|
+
case "steer": {
|
|
8229
|
+
const runOption = takeOption(rest, "--run");
|
|
8230
|
+
const messageOption = takeOption(runOption.rest, "--message");
|
|
8231
|
+
const shortMessageOption = takeOption(messageOption.rest, "-m");
|
|
8232
|
+
const positionalRunId = shortMessageOption.rest.length > 0 ? shortMessageOption.rest[0] : undefined;
|
|
8233
|
+
const extra = positionalRunId ? shortMessageOption.rest.slice(1) : shortMessageOption.rest;
|
|
8234
|
+
requireNoExtraArgs(extra, "rig run steer [<run-id>|--run <id>] --message <text>");
|
|
8235
|
+
const runId = runOption.value ?? positionalRunId;
|
|
8236
|
+
const message2 = messageOption.value ?? shortMessageOption.value;
|
|
8237
|
+
if (!runId) {
|
|
8238
|
+
throw new CliError2("run steer requires a run id (positional or --run <id>).", 2);
|
|
8239
|
+
}
|
|
8240
|
+
if (!message2?.trim()) {
|
|
8241
|
+
throw new CliError2("run steer requires --message <text>.", 2);
|
|
8242
|
+
}
|
|
8243
|
+
if (context.dryRun) {
|
|
8244
|
+
if (context.outputMode === "text") {
|
|
8245
|
+
console.log(`[dry-run] rig run steer ${runId} --message ${JSON.stringify(message2)}`);
|
|
8246
|
+
}
|
|
8247
|
+
return { ok: true, group: "run", command, details: { runId, dryRun: true } };
|
|
8248
|
+
}
|
|
8249
|
+
await steerRunViaServer(context, runId, message2.trim());
|
|
8250
|
+
if (context.outputMode === "text") {
|
|
8251
|
+
console.log(`Steering message queued for ${runId}.`);
|
|
8252
|
+
}
|
|
8253
|
+
return { ok: true, group: "run", command, details: { runId, queued: true } };
|
|
8254
|
+
}
|
|
8077
8255
|
case "stop": {
|
|
8078
8256
|
const runOption = takeOption(rest, "--run");
|
|
8079
8257
|
const positionalRunId = runOption.rest.length > 0 ? runOption.rest[0] : undefined;
|
|
@@ -8220,9 +8398,9 @@ async function executeServer(context, args, options) {
|
|
|
8220
8398
|
|
|
8221
8399
|
// packages/cli/src/commands/task.ts
|
|
8222
8400
|
init_runner();
|
|
8223
|
-
import { readFileSync as
|
|
8401
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
8224
8402
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
8225
|
-
import { resolve as
|
|
8403
|
+
import { resolve as resolve21 } from "path";
|
|
8226
8404
|
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
8227
8405
|
import {
|
|
8228
8406
|
taskArtifactDir,
|
|
@@ -8400,6 +8578,7 @@ var PRIMARY_GROUPS = [
|
|
|
8400
8578
|
{ command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
|
|
8401
8579
|
{ command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; --follow launches native bundled Pi for live Pi runs.", primary: true },
|
|
8402
8580
|
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
8581
|
+
{ command: "steer <run-id> --message <text>", description: "Queue a steering message into a live worker without attaching." },
|
|
8403
8582
|
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
8404
8583
|
{ command: "resume", description: "Resume the most recent interrupted local run." },
|
|
8405
8584
|
{ command: "restart", description: "Restart the most recent local run from a clean runtime." },
|
|
@@ -8501,6 +8680,19 @@ var ADVANCED_GROUPS = [
|
|
|
8501
8680
|
{ command: "hp-next <dev|check|e2e|reset>", description: "Drive the hp-next browser test harness." }
|
|
8502
8681
|
]
|
|
8503
8682
|
},
|
|
8683
|
+
{
|
|
8684
|
+
name: "pi",
|
|
8685
|
+
summary: "Manage Pi extension packages for this project (community extensions from npm/git).",
|
|
8686
|
+
usage: ["rig pi <list|add|remove|search> [args]"],
|
|
8687
|
+
commands: [
|
|
8688
|
+
{ command: "list", description: "Show project and user Pi extension packages." },
|
|
8689
|
+
{ command: "add <source>", description: "Add an npm/git Pi extension to .pi/settings.json (auto-installs at next session)." },
|
|
8690
|
+
{ command: "remove <source>", description: "Remove an operator-added Pi extension." },
|
|
8691
|
+
{ command: "search [term]", description: "Discover Pi extension packages on the npm registry." }
|
|
8692
|
+
],
|
|
8693
|
+
examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
|
|
8694
|
+
next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
|
|
8695
|
+
},
|
|
8504
8696
|
{
|
|
8505
8697
|
name: "plugin",
|
|
8506
8698
|
summary: "Plugin listing, validation, and plugin-contributed commands.",
|
|
@@ -8931,7 +9123,7 @@ async function executeTask(context, args, options) {
|
|
|
8931
9123
|
const fileFlag = takeOption(rest.slice(1), "--file");
|
|
8932
9124
|
let content;
|
|
8933
9125
|
if (fileFlag.value) {
|
|
8934
|
-
content =
|
|
9126
|
+
content = readFileSync10(resolve21(context.projectRoot, fileFlag.value), "utf-8");
|
|
8935
9127
|
} else {
|
|
8936
9128
|
content = await readStdin();
|
|
8937
9129
|
}
|
|
@@ -9165,8 +9357,8 @@ async function executeTask(context, args, options) {
|
|
|
9165
9357
|
|
|
9166
9358
|
// packages/cli/src/commands/task-run-driver.ts
|
|
9167
9359
|
init_runner();
|
|
9168
|
-
import { copyFileSync as copyFileSync3, existsSync as
|
|
9169
|
-
import { resolve as
|
|
9360
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync11, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
9361
|
+
import { resolve as resolve22 } from "path";
|
|
9170
9362
|
import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
|
|
9171
9363
|
import { createInterface as createLineInterface } from "readline";
|
|
9172
9364
|
import { loadConfig as loadConfig2 } from "@rig/core/load-config";
|
|
@@ -9249,12 +9441,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
|
|
|
9249
9441
|
return 0;
|
|
9250
9442
|
let copied = 0;
|
|
9251
9443
|
for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
|
|
9252
|
-
const sourcePath =
|
|
9253
|
-
const targetPath =
|
|
9444
|
+
const sourcePath = resolve22(sourceRoot, relativePath);
|
|
9445
|
+
const targetPath = resolve22(targetRoot, relativePath);
|
|
9254
9446
|
try {
|
|
9255
9447
|
if (!statSync2(sourcePath).isFile())
|
|
9256
9448
|
continue;
|
|
9257
|
-
|
|
9449
|
+
mkdirSync8(resolve22(targetPath, ".."), { recursive: true });
|
|
9258
9450
|
copyFileSync3(sourcePath, targetPath);
|
|
9259
9451
|
copied += 1;
|
|
9260
9452
|
} catch {}
|
|
@@ -9293,7 +9485,7 @@ function buildDirtyBaselineHandshakeEnv(input) {
|
|
|
9293
9485
|
return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
|
|
9294
9486
|
return {
|
|
9295
9487
|
RIG_BASELINE_MODE: "dirty-snapshot",
|
|
9296
|
-
RIG_DIRTY_BASELINE_READY_FILE:
|
|
9488
|
+
RIG_DIRTY_BASELINE_READY_FILE: resolve22(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
|
|
9297
9489
|
};
|
|
9298
9490
|
}
|
|
9299
9491
|
function positiveInt(value, fallback) {
|
|
@@ -9404,9 +9596,9 @@ function createCommandRunner(binary) {
|
|
|
9404
9596
|
const stderrChunks = [];
|
|
9405
9597
|
child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
9406
9598
|
child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
|
|
9407
|
-
return await new Promise((
|
|
9408
|
-
child.once("error", (error) =>
|
|
9409
|
-
child.once("close", (code) =>
|
|
9599
|
+
return await new Promise((resolve23) => {
|
|
9600
|
+
child.once("error", (error) => resolve23({ exitCode: 1, stderr: error.message }));
|
|
9601
|
+
child.once("close", (code) => resolve23({
|
|
9410
9602
|
exitCode: code ?? 1,
|
|
9411
9603
|
stdout: Buffer.concat(stdoutChunks).toString("utf8"),
|
|
9412
9604
|
stderr: Buffer.concat(stderrChunks).toString("utf8")
|
|
@@ -9480,7 +9672,7 @@ async function runTaskRunPostValidationLifecycle(input) {
|
|
|
9480
9672
|
config,
|
|
9481
9673
|
sourceTask: input.sourceTask,
|
|
9482
9674
|
uploadedSnapshot: input.uploadedSnapshot,
|
|
9483
|
-
artifactRoot:
|
|
9675
|
+
artifactRoot: resolve22(input.projectRoot, "artifacts", taskId3),
|
|
9484
9676
|
command: ghCommand,
|
|
9485
9677
|
gitCommand,
|
|
9486
9678
|
steerPi,
|
|
@@ -9610,7 +9802,7 @@ function summarizeValidationFailure(projectRoot, taskId3) {
|
|
|
9610
9802
|
return null;
|
|
9611
9803
|
}
|
|
9612
9804
|
for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId3)) {
|
|
9613
|
-
const summary = readJsonFile3(
|
|
9805
|
+
const summary = readJsonFile3(resolve22(artifactDir, "validation-summary.json"), null);
|
|
9614
9806
|
if (!summary || summary.status !== "fail") {
|
|
9615
9807
|
continue;
|
|
9616
9808
|
}
|
|
@@ -9691,9 +9883,9 @@ function readTaskRunAcceptedArtifactState(input) {
|
|
|
9691
9883
|
if (!input.taskId || !input.workspaceDir) {
|
|
9692
9884
|
return { accepted: false, reason: null };
|
|
9693
9885
|
}
|
|
9694
|
-
const artifactDir =
|
|
9695
|
-
const reviewStatusPath =
|
|
9696
|
-
const taskResultPath =
|
|
9886
|
+
const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
|
|
9887
|
+
const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
|
|
9888
|
+
const taskResultPath = resolve22(artifactDir, "task-result.json");
|
|
9697
9889
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
9698
9890
|
if (reviewStatus !== "APPROVED") {
|
|
9699
9891
|
return { accepted: false, reason: null };
|
|
@@ -9730,12 +9922,12 @@ function resolveTaskRunRetryContext(input) {
|
|
|
9730
9922
|
if (!input.taskId || !input.workspaceDir) {
|
|
9731
9923
|
return { shouldRetry: false, failureDetail: null, nextPrompt: null };
|
|
9732
9924
|
}
|
|
9733
|
-
const artifactDir =
|
|
9734
|
-
const reviewStatePath =
|
|
9735
|
-
const reviewFeedbackPath =
|
|
9736
|
-
const reviewStatusPath =
|
|
9737
|
-
const failedApproachesPath =
|
|
9738
|
-
const validationSummaryPath =
|
|
9925
|
+
const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
|
|
9926
|
+
const reviewStatePath = resolve22(artifactDir, "review-state.json");
|
|
9927
|
+
const reviewFeedbackPath = resolve22(artifactDir, "review-feedback.md");
|
|
9928
|
+
const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
|
|
9929
|
+
const failedApproachesPath = resolve22(input.workspaceDir, ".rig", "state", "failed_approaches.md");
|
|
9930
|
+
const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
|
|
9739
9931
|
const reviewState = readJsonFile3(reviewStatePath, null);
|
|
9740
9932
|
const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
|
|
9741
9933
|
const reviewRejected = isTaskRunReviewRejected(reviewState);
|
|
@@ -9921,11 +10113,11 @@ function appendToolTimelineFromLog(input) {
|
|
|
9921
10113
|
});
|
|
9922
10114
|
}
|
|
9923
10115
|
function readTaskRunReviewStatus(reviewStatusPath) {
|
|
9924
|
-
if (!
|
|
10116
|
+
if (!existsSync13(reviewStatusPath)) {
|
|
9925
10117
|
return null;
|
|
9926
10118
|
}
|
|
9927
10119
|
try {
|
|
9928
|
-
const status =
|
|
10120
|
+
const status = readFileSync11(reviewStatusPath, "utf8").trim().toUpperCase();
|
|
9929
10121
|
return status === "APPROVED" || status === "REJECTED" ? status : null;
|
|
9930
10122
|
} catch {
|
|
9931
10123
|
return null;
|
|
@@ -10139,15 +10331,15 @@ async function executeRigOwnedTaskRun(context, input) {
|
|
|
10139
10331
|
const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
|
|
10140
10332
|
const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
|
|
10141
10333
|
const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
|
|
10142
|
-
const planningArtifactPath =
|
|
10334
|
+
const planningArtifactPath = resolve22("artifacts", runtimeTaskId, "implementation-plan.md");
|
|
10143
10335
|
const persistedPlanning = {
|
|
10144
10336
|
...planningClassification,
|
|
10145
10337
|
classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
|
|
10146
10338
|
artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
|
|
10147
10339
|
classifiedAt: new Date().toISOString()
|
|
10148
10340
|
};
|
|
10149
|
-
|
|
10150
|
-
|
|
10341
|
+
mkdirSync8(resolve22(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
|
|
10342
|
+
writeFileSync7(resolve22(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
|
|
10151
10343
|
`, "utf8");
|
|
10152
10344
|
patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
|
|
10153
10345
|
prompt = `${prompt}
|
|
@@ -10197,7 +10389,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10197
10389
|
let verificationStarted = false;
|
|
10198
10390
|
let reviewStarted = false;
|
|
10199
10391
|
let latestRuntimeWorkspace = resumeMode && typeof existingRunRecord?.worktreePath === "string" ? existingRunRecord.worktreePath : null;
|
|
10200
|
-
let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ?
|
|
10392
|
+
let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve22(existingRunRecord.sessionPath, "..") : null;
|
|
10201
10393
|
let latestLogsDir = resumeMode && typeof existingRunRecord?.logRoot === "string" ? existingRunRecord.logRoot : null;
|
|
10202
10394
|
let latestProviderCommand = null;
|
|
10203
10395
|
let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
|
|
@@ -10283,10 +10475,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10283
10475
|
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
10284
10476
|
status: "running",
|
|
10285
10477
|
worktreePath: latestRuntimeWorkspace,
|
|
10286
|
-
artifactRoot: latestRuntimeWorkspace && input.taskId ?
|
|
10478
|
+
artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve22(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
|
|
10287
10479
|
logRoot: latestLogsDir,
|
|
10288
|
-
sessionPath: latestSessionDir ?
|
|
10289
|
-
sessionLogPath: latestLogsDir ?
|
|
10480
|
+
sessionPath: latestSessionDir ? resolve22(latestSessionDir, "session.json") : null,
|
|
10481
|
+
sessionLogPath: latestLogsDir ? resolve22(latestLogsDir, "agent-stdout.log") : null,
|
|
10290
10482
|
branch: runtimeId
|
|
10291
10483
|
});
|
|
10292
10484
|
if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
|
|
@@ -10294,8 +10486,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10294
10486
|
const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
|
|
10295
10487
|
const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
|
|
10296
10488
|
if (readyFile) {
|
|
10297
|
-
|
|
10298
|
-
|
|
10489
|
+
mkdirSync8(resolve22(readyFile, ".."), { recursive: true });
|
|
10490
|
+
writeFileSync7(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
|
|
10299
10491
|
`, "utf8");
|
|
10300
10492
|
}
|
|
10301
10493
|
appendRunLog(context.projectRoot, input.runId, {
|
|
@@ -10679,7 +10871,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10679
10871
|
let acceptedArtifactObservedAt = null;
|
|
10680
10872
|
let acceptedArtifactPollTimer = null;
|
|
10681
10873
|
let acceptedArtifactKillTimer = null;
|
|
10682
|
-
const attemptExit = await new Promise((
|
|
10874
|
+
const attemptExit = await new Promise((resolve23) => {
|
|
10683
10875
|
let settled = false;
|
|
10684
10876
|
const settle = (result) => {
|
|
10685
10877
|
if (settled)
|
|
@@ -10687,7 +10879,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
|
|
|
10687
10879
|
settled = true;
|
|
10688
10880
|
if (acceptedArtifactPollTimer)
|
|
10689
10881
|
clearInterval(acceptedArtifactPollTimer);
|
|
10690
|
-
|
|
10882
|
+
resolve23(result);
|
|
10691
10883
|
};
|
|
10692
10884
|
const pollAcceptedArtifacts = () => {
|
|
10693
10885
|
const artifactState = readTaskRunAcceptedArtifactState({
|
|
@@ -10889,8 +11081,8 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
10889
11081
|
}
|
|
10890
11082
|
if (planningClassification.planningRequired) {
|
|
10891
11083
|
const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
|
|
10892
|
-
const expectedPlanPath =
|
|
10893
|
-
if (!
|
|
11084
|
+
const expectedPlanPath = resolve22(planWorkspace, planningArtifactPath);
|
|
11085
|
+
if (!existsSync13(expectedPlanPath)) {
|
|
10894
11086
|
const failedAt = new Date().toISOString();
|
|
10895
11087
|
const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
|
|
10896
11088
|
patchAuthorityRun(context.projectRoot, input.runId, {
|
|
@@ -11060,9 +11252,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
|
|
|
11060
11252
|
});
|
|
11061
11253
|
emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
|
|
11062
11254
|
});
|
|
11063
|
-
const exitCode = await new Promise((
|
|
11064
|
-
child.once("error", () =>
|
|
11065
|
-
child.once("close", (code) =>
|
|
11255
|
+
const exitCode = await new Promise((resolve23) => {
|
|
11256
|
+
child.once("error", () => resolve23(1));
|
|
11257
|
+
child.once("close", (code) => resolve23(code ?? 1));
|
|
11066
11258
|
});
|
|
11067
11259
|
for (const pendingLog of flushPendingClaudeToolUseLogs({
|
|
11068
11260
|
runId: input.runId,
|
|
@@ -11204,8 +11396,8 @@ async function executeTest(context, args) {
|
|
|
11204
11396
|
|
|
11205
11397
|
// packages/cli/src/commands/setup.ts
|
|
11206
11398
|
init_runner();
|
|
11207
|
-
import { existsSync as
|
|
11208
|
-
import { resolve as
|
|
11399
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync9, readdirSync as readdirSync2, writeFileSync as writeFileSync8 } from "fs";
|
|
11400
|
+
import { resolve as resolve23 } from "path";
|
|
11209
11401
|
import { createPluginHost } from "@rig/core";
|
|
11210
11402
|
import {
|
|
11211
11403
|
isSupportedBunVersion as isSupportedBunVersion2,
|
|
@@ -11260,12 +11452,12 @@ function runSetupInit(projectRoot) {
|
|
|
11260
11452
|
const stateDir = resolveControlPlaneHostStateDir(projectRoot);
|
|
11261
11453
|
const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
|
|
11262
11454
|
const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
|
|
11263
|
-
|
|
11264
|
-
|
|
11265
|
-
|
|
11266
|
-
const failuresPath =
|
|
11267
|
-
if (!
|
|
11268
|
-
|
|
11455
|
+
mkdirSync9(stateDir, { recursive: true });
|
|
11456
|
+
mkdirSync9(logsDir, { recursive: true });
|
|
11457
|
+
mkdirSync9(artifactsDir, { recursive: true });
|
|
11458
|
+
const failuresPath = resolve23(stateDir, "failed_approaches.md");
|
|
11459
|
+
if (!existsSync14(failuresPath)) {
|
|
11460
|
+
writeFileSync8(failuresPath, `# Failed Approaches
|
|
11269
11461
|
|
|
11270
11462
|
`, "utf-8");
|
|
11271
11463
|
}
|
|
@@ -11282,18 +11474,18 @@ async function runSetupCheck(projectRoot) {
|
|
|
11282
11474
|
}
|
|
11283
11475
|
async function runSetupPreflight(projectRoot) {
|
|
11284
11476
|
await runSetupCheck(projectRoot);
|
|
11285
|
-
const validationRoot =
|
|
11286
|
-
if (
|
|
11477
|
+
const validationRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
|
|
11478
|
+
if (existsSync14(validationRoot)) {
|
|
11287
11479
|
const validators = readdirSync2(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
|
|
11288
11480
|
for (const validator of validators) {
|
|
11289
|
-
const script =
|
|
11290
|
-
if (
|
|
11481
|
+
const script = resolve23(validationRoot, validator.name, "validate.sh");
|
|
11482
|
+
if (existsSync14(script)) {
|
|
11291
11483
|
console.log(`OK: validator script ${script}`);
|
|
11292
11484
|
}
|
|
11293
11485
|
}
|
|
11294
11486
|
}
|
|
11295
|
-
const hooksRoot =
|
|
11296
|
-
if (
|
|
11487
|
+
const hooksRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
|
|
11488
|
+
if (existsSync14(hooksRoot)) {
|
|
11297
11489
|
const hooks = readdirSync2(hooksRoot).filter((name) => name.endsWith(".sh"));
|
|
11298
11490
|
for (const hook of hooks) {
|
|
11299
11491
|
console.log(`OK: hook ${hook}`);
|
|
@@ -11438,7 +11630,7 @@ var PROJECT_REQUIRED_GROUPS = new Set([
|
|
|
11438
11630
|
]);
|
|
11439
11631
|
var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
|
|
11440
11632
|
function hasInitializedRigProject(projectRoot) {
|
|
11441
|
-
return RIG_CONFIG_FILENAMES.some((name) =>
|
|
11633
|
+
return RIG_CONFIG_FILENAMES.some((name) => existsSync15(resolve24(projectRoot, name))) || existsSync15(resolve24(projectRoot, ".rig"));
|
|
11442
11634
|
}
|
|
11443
11635
|
function requireInitializedRigProject(context, group) {
|
|
11444
11636
|
if (hasInitializedRigProject(context.projectRoot)) {
|
|
@@ -11464,6 +11656,7 @@ var GROUPS = new Set([
|
|
|
11464
11656
|
"review",
|
|
11465
11657
|
"git",
|
|
11466
11658
|
"harness",
|
|
11659
|
+
"pi",
|
|
11467
11660
|
"plugin",
|
|
11468
11661
|
"queue",
|
|
11469
11662
|
"agent",
|
|
@@ -11609,6 +11802,8 @@ async function executeGroup(context, group, args) {
|
|
|
11609
11802
|
return executeGit(context, args);
|
|
11610
11803
|
case "harness":
|
|
11611
11804
|
return executeHarness(context, args);
|
|
11805
|
+
case "pi":
|
|
11806
|
+
return executePi(context, args);
|
|
11612
11807
|
case "plugin":
|
|
11613
11808
|
return executePlugin(context, args);
|
|
11614
11809
|
case "queue":
|