@h-rig/cli 0.0.6-alpha.26 → 0.0.6-alpha.28
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 +1043 -596
- package/dist/src/commands/_cli-format.js +211 -6
- package/dist/src/commands/_connection-state.js +1 -1
- package/dist/src/commands/_doctor-checks.js +3 -3
- package/dist/src/commands/_help-catalog.js +231 -41
- package/dist/src/commands/_operator-view.js +1 -1
- package/dist/src/commands/_pi-frontend.js +1 -1
- package/dist/src/commands/_pi-worker-bridge-extension.js +1 -1
- package/dist/src/commands/_preflight.js +2 -2
- package/dist/src/commands/_server-client.js +1 -1
- package/dist/src/commands/_snapshot-upload.js +1 -1
- package/dist/src/commands/agent.js +7 -7
- package/dist/src/commands/browser.js +4 -4
- package/dist/src/commands/connect.js +5 -4
- package/dist/src/commands/dist.js +4 -4
- package/dist/src/commands/doctor.js +3 -3
- package/dist/src/commands/github.js +1 -1
- package/dist/src/commands/inbox.js +351 -29
- package/dist/src/commands/init.js +3 -3
- package/dist/src/commands/inspect.js +10 -10
- package/dist/src/commands/inspector.js +2 -2
- package/dist/src/commands/plugin.js +3 -3
- package/dist/src/commands/profile-and-review.js +8 -8
- package/dist/src/commands/queue.js +1 -1
- package/dist/src/commands/remote.js +18 -18
- package/dist/src/commands/repo-git-harness.js +4 -4
- package/dist/src/commands/run.js +157 -37
- package/dist/src/commands/server.js +6 -5
- package/dist/src/commands/setup.js +8 -8
- package/dist/src/commands/task-report-bug.js +5 -5
- package/dist/src/commands/task-run-driver.js +1 -1
- package/dist/src/commands/task.js +451 -45
- package/dist/src/commands/test.js +3 -3
- package/dist/src/commands/workspace.js +4 -4
- package/dist/src/commands.js +1043 -596
- package/dist/src/index.js +1043 -596
- package/dist/src/report-bug.js +3 -3
- package/package.json +6 -6
package/dist/bin/rig.js
CHANGED
|
@@ -495,15 +495,15 @@ function buildBugReportMarkdown(input, browser, screenshots, assets) {
|
|
|
495
495
|
...input.issueId ? [
|
|
496
496
|
`- Canonical task assets live under \`artifacts/${input.issueId}/bug-report/\`.`,
|
|
497
497
|
`- Start with \`artifacts/${input.issueId}/bug-report/task.md\` and the files in \`artifacts/${input.issueId}/bug-report/assets/\`.`,
|
|
498
|
-
browserRequired ? `- Run \`
|
|
498
|
+
browserRequired ? `- Run \`rig task info --task ${input.issueId}\` to confirm browser wiring before debugging.` : `- Run \`rig task info --task ${input.issueId}\` to confirm scope and artifact links before debugging.`
|
|
499
499
|
] : [
|
|
500
|
-
"- Draft-only report: convert this into a
|
|
500
|
+
"- Draft-only report: convert this into a Rig task before assigning it to an agent run."
|
|
501
501
|
],
|
|
502
502
|
"",
|
|
503
503
|
"## Validation",
|
|
504
504
|
"",
|
|
505
505
|
"```bash",
|
|
506
|
-
...input.issueId ? [`
|
|
506
|
+
...input.issueId ? [`rig task validate --task ${input.issueId}`] : [],
|
|
507
507
|
...browserRequired ? [
|
|
508
508
|
"bun run app:check:browser:hp-next",
|
|
509
509
|
"bun run app:e2e:browser:hp-next"
|
|
@@ -650,7 +650,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
650
650
|
pending = outputRootResult.rest;
|
|
651
651
|
const slugResult = takeOption(pending, "--slug");
|
|
652
652
|
pending = slugResult.rest;
|
|
653
|
-
requireNoExtraArgs(pending, "
|
|
653
|
+
requireNoExtraArgs(pending, "rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
|
|
654
654
|
let draft = {
|
|
655
655
|
outputRoot: outputRootResult.value || "",
|
|
656
656
|
title: titleResult.value,
|
|
@@ -755,7 +755,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
755
755
|
console.log(`Evidence assets: ${result.assetDir}`);
|
|
756
756
|
if (taskConfigPath) {
|
|
757
757
|
console.log(`Task config: ${taskConfigPath}`);
|
|
758
|
-
console.log(`Run:
|
|
758
|
+
console.log(`Run: rig task info --task ${issueId}`);
|
|
759
759
|
}
|
|
760
760
|
}
|
|
761
761
|
return {
|
|
@@ -1578,7 +1578,7 @@ async function executeBrowser(context, args) {
|
|
|
1578
1578
|
return { ok: true, group: "browser", command: "help" };
|
|
1579
1579
|
}
|
|
1580
1580
|
if (command === "explain") {
|
|
1581
|
-
requireNoExtraArgs(rest, "
|
|
1581
|
+
requireNoExtraArgs(rest, "rig browser explain");
|
|
1582
1582
|
console.log(browserAgentUsageText());
|
|
1583
1583
|
return { ok: true, group: "browser", command: "explain" };
|
|
1584
1584
|
}
|
|
@@ -1604,7 +1604,7 @@ ${browserHelpText()}`);
|
|
|
1604
1604
|
|
|
1605
1605
|
${browserHelpText()}`);
|
|
1606
1606
|
}
|
|
1607
|
-
requireNoExtraArgs(appRest, `
|
|
1607
|
+
requireNoExtraArgs(appRest, `rig browser ${command} ${subcommand}`);
|
|
1608
1608
|
await context.runCommand(["bun", "run", `app:${subcommand}:browser:${appSlug}`]);
|
|
1609
1609
|
return { ok: true, group: "browser", command: `${command}-${subcommand}` };
|
|
1610
1610
|
}
|
|
@@ -1616,7 +1616,7 @@ ${browserHelpText()}`);
|
|
|
1616
1616
|
};
|
|
1617
1617
|
const packageScript = packageScripts[command];
|
|
1618
1618
|
if (packageScript) {
|
|
1619
|
-
requireNoExtraArgs(rest, `
|
|
1619
|
+
requireNoExtraArgs(rest, `rig browser ${command}`);
|
|
1620
1620
|
await context.runCommand(["bun", "run", "--filter=@rig/browser", packageScript]);
|
|
1621
1621
|
return { ok: true, group: "browser", command };
|
|
1622
1622
|
}
|
|
@@ -1643,7 +1643,7 @@ async function executeBrowserDemo(context, args) {
|
|
|
1643
1643
|
pending = keepOpenFlag.rest;
|
|
1644
1644
|
const noBuildFlag = takeFlag(pending, "--no-build");
|
|
1645
1645
|
pending = noBuildFlag.rest;
|
|
1646
|
-
requireNoExtraArgs(pending, "
|
|
1646
|
+
requireNoExtraArgs(pending, "rig browser demo [--port <n>] [--profile <name>] [--state-dir <path>] [--target-url <url>] [--keep-open] [--no-build]");
|
|
1647
1647
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1648
1648
|
throw new CliError2("rig browser demo requires an interactive TTY in text mode.");
|
|
1649
1649
|
}
|
|
@@ -2154,17 +2154,17 @@ async function executeProfile(context, args) {
|
|
|
2154
2154
|
const [command = "show", ...rest] = args;
|
|
2155
2155
|
switch (command) {
|
|
2156
2156
|
case "show":
|
|
2157
|
-
requireNoExtraArgs(rest, "
|
|
2157
|
+
requireNoExtraArgs(rest, "rig profile show");
|
|
2158
2158
|
await withMutedConsole(context.outputMode === "json", () => showProfile(context.projectRoot));
|
|
2159
2159
|
return { ok: true, group: "profile", command };
|
|
2160
2160
|
case "set": {
|
|
2161
2161
|
if (rest.length === 0) {
|
|
2162
|
-
throw new CliError2("Usage:
|
|
2162
|
+
throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi> or set [--model ...] [--runtime ...] [--plugin ...]");
|
|
2163
2163
|
}
|
|
2164
2164
|
const preset = rest[0];
|
|
2165
2165
|
if (preset && !preset.startsWith("-")) {
|
|
2166
2166
|
if (rest.length !== 1) {
|
|
2167
|
-
throw new CliError2("Usage:
|
|
2167
|
+
throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi>");
|
|
2168
2168
|
}
|
|
2169
2169
|
try {
|
|
2170
2170
|
await withMutedConsole(context.outputMode === "json", () => setProfile(context.projectRoot, { preset }));
|
|
@@ -2180,7 +2180,7 @@ async function executeProfile(context, args) {
|
|
|
2180
2180
|
pending = runtimeResult.rest;
|
|
2181
2181
|
const pluginResult = takeOption(pending, "--plugin");
|
|
2182
2182
|
pending = pluginResult.rest;
|
|
2183
|
-
requireNoExtraArgs(pending, "
|
|
2183
|
+
requireNoExtraArgs(pending, "rig profile set [--model ...] [--runtime ...] [--plugin ...]");
|
|
2184
2184
|
if (!modelResult.value && !runtimeResult.value && !pluginResult.value) {
|
|
2185
2185
|
throw new CliError2("Provide at least one of --model, --runtime, or --plugin.");
|
|
2186
2186
|
}
|
|
@@ -2212,21 +2212,21 @@ async function executeReview(context, args) {
|
|
|
2212
2212
|
const [command = "show", ...rest] = args;
|
|
2213
2213
|
switch (command) {
|
|
2214
2214
|
case "show":
|
|
2215
|
-
requireNoExtraArgs(rest, "
|
|
2215
|
+
requireNoExtraArgs(rest, "rig review show");
|
|
2216
2216
|
await withMutedConsole(context.outputMode === "json", () => showReviewProfile(context.projectRoot));
|
|
2217
2217
|
return { ok: true, group: "review", command };
|
|
2218
2218
|
case "set": {
|
|
2219
2219
|
if (rest.length === 0) {
|
|
2220
|
-
throw new CliError2("Usage:
|
|
2220
|
+
throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
|
|
2221
2221
|
}
|
|
2222
2222
|
const mode = rest[0];
|
|
2223
2223
|
if (!mode) {
|
|
2224
|
-
throw new CliError2("Usage:
|
|
2224
|
+
throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
|
|
2225
2225
|
}
|
|
2226
2226
|
let pending = rest.slice(1);
|
|
2227
2227
|
const providerResult = takeOption(pending, "--provider");
|
|
2228
2228
|
pending = providerResult.rest;
|
|
2229
|
-
requireNoExtraArgs(pending, "
|
|
2229
|
+
requireNoExtraArgs(pending, "rig review set <off|advisory|required> [--provider greptile]");
|
|
2230
2230
|
try {
|
|
2231
2231
|
await withMutedConsole(context.outputMode === "json", () => {
|
|
2232
2232
|
return setReviewProfile(context.projectRoot, mode, providerResult.value);
|
|
@@ -2311,13 +2311,13 @@ async function executeRepo(context, args) {
|
|
|
2311
2311
|
switch (command) {
|
|
2312
2312
|
case "sync": {
|
|
2313
2313
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
2314
|
-
requireNoExtraArgs(remaining, "
|
|
2314
|
+
requireNoExtraArgs(remaining, "rig repo sync [--task <task-id>]");
|
|
2315
2315
|
withMutedConsole(context.outputMode === "json", () => repoEnsure(context.projectRoot, task || undefined));
|
|
2316
2316
|
return { ok: true, group: "repo", command, details: { task: task || null } };
|
|
2317
2317
|
}
|
|
2318
2318
|
case "reset-baseline": {
|
|
2319
2319
|
const { value: keepTaskStatusFlag, rest: remaining } = takeFlag(rest, "--keep-task-status");
|
|
2320
|
-
requireNoExtraArgs(remaining, "
|
|
2320
|
+
requireNoExtraArgs(remaining, "rig repo reset-baseline [--keep-task-status]");
|
|
2321
2321
|
withMutedConsole(context.outputMode === "json", () => resetBaseline(context.projectRoot, keepTaskStatusFlag));
|
|
2322
2322
|
return { ok: true, group: "repo", command, details: { keepTaskStatus: keepTaskStatusFlag } };
|
|
2323
2323
|
}
|
|
@@ -2327,7 +2327,7 @@ async function executeRepo(context, args) {
|
|
|
2327
2327
|
}
|
|
2328
2328
|
async function executeGit(context, args) {
|
|
2329
2329
|
if (args.length === 0) {
|
|
2330
|
-
throw new CliError2("Usage:
|
|
2330
|
+
throw new CliError2("Usage: rig git <git-flow args...>");
|
|
2331
2331
|
}
|
|
2332
2332
|
await enforceNativeCommandPolicy(context, args, {
|
|
2333
2333
|
commandPrefix: "rig-agent git",
|
|
@@ -2348,7 +2348,7 @@ async function executeGit(context, args) {
|
|
|
2348
2348
|
}
|
|
2349
2349
|
async function executeHarness(context, args) {
|
|
2350
2350
|
if (args.length === 0) {
|
|
2351
|
-
throw new CliError2("Usage:
|
|
2351
|
+
throw new CliError2("Usage: rig harness <harness args...>");
|
|
2352
2352
|
}
|
|
2353
2353
|
await enforceNativeCommandPolicy(context, args, {
|
|
2354
2354
|
commandPrefix: "rig-agent",
|
|
@@ -2457,7 +2457,7 @@ async function executePlugin(context, args) {
|
|
|
2457
2457
|
const [command = "list", ...rest] = args;
|
|
2458
2458
|
switch (command) {
|
|
2459
2459
|
case "list": {
|
|
2460
|
-
requireNoExtraArgs(rest, "
|
|
2460
|
+
requireNoExtraArgs(rest, "rig plugin list");
|
|
2461
2461
|
const legacyPlugins = context.plugins.list();
|
|
2462
2462
|
const declarative = [];
|
|
2463
2463
|
const config = await loadRigConfigOrNull(context.projectRoot);
|
|
@@ -2524,8 +2524,8 @@ async function executePlugin(context, args) {
|
|
|
2524
2524
|
}
|
|
2525
2525
|
case "validate": {
|
|
2526
2526
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
2527
|
-
requireNoExtraArgs(remaining, "
|
|
2528
|
-
const taskId = requireTask(task, "
|
|
2527
|
+
requireNoExtraArgs(remaining, "rig plugin validate --task <task-id>");
|
|
2528
|
+
const taskId = requireTask(task, "rig plugin validate --task <task-id>");
|
|
2529
2529
|
const results = await context.plugins.runValidators(taskId);
|
|
2530
2530
|
const passed = results.filter((result) => result.passed).length;
|
|
2531
2531
|
const failed = results.length - passed;
|
|
@@ -2665,7 +2665,7 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
2665
2665
|
const global = readGlobalConnections(options);
|
|
2666
2666
|
const connection = global.connections[repo.selected];
|
|
2667
2667
|
if (!connection) {
|
|
2668
|
-
throw new CliError2(`Selected Rig
|
|
2668
|
+
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
2669
2669
|
}
|
|
2670
2670
|
return { alias: repo.selected, connection };
|
|
2671
2671
|
}
|
|
@@ -3157,7 +3157,7 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
3157
3157
|
}
|
|
3158
3158
|
}
|
|
3159
3159
|
const repo = readRepoConnection(context.projectRoot);
|
|
3160
|
-
checks.push(repo ? preflightCheck("project-link", "project linked to Rig
|
|
3160
|
+
checks.push(repo ? preflightCheck("project-link", "project linked to Rig server", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to record the GitHub repo slug.") : preflightCheck("project-link", "project linked to Rig server", legacyServerCompatibility ? "warn" : "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
|
|
3161
3161
|
try {
|
|
3162
3162
|
const auth = await request("/api/github/auth/status");
|
|
3163
3163
|
checks.push(isAuthenticated(auth) ? preflightCheck("github-auth", "GitHub auth valid", "pass") : preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", "not authenticated", "Run `rig github auth import-gh` or `rig github auth token --token <token>`."));
|
|
@@ -3275,7 +3275,7 @@ async function executeQueue(context, args) {
|
|
|
3275
3275
|
pending = failFastResult.rest;
|
|
3276
3276
|
const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
|
|
3277
3277
|
pending = skipProjectSyncResult.rest;
|
|
3278
|
-
requireNoExtraArgs(pending, "
|
|
3278
|
+
requireNoExtraArgs(pending, "rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]");
|
|
3279
3279
|
const workers = parsePositiveInt(workersResult.value, "--workers", 2);
|
|
3280
3280
|
const maxTasks = parsePositiveInt(maxTasksResult.value, "--max-tasks", 10);
|
|
3281
3281
|
const action = parseAction(actionResult.value);
|
|
@@ -3453,7 +3453,7 @@ async function executeAgent(context, args) {
|
|
|
3453
3453
|
const [command = "list", ...rest] = args;
|
|
3454
3454
|
switch (command) {
|
|
3455
3455
|
case "list": {
|
|
3456
|
-
requireNoExtraArgs(rest, "
|
|
3456
|
+
requireNoExtraArgs(rest, "rig agent list");
|
|
3457
3457
|
const runtimes = await listAgentRuntimes(context.projectRoot);
|
|
3458
3458
|
if (context.outputMode === "text") {
|
|
3459
3459
|
if (runtimes.length === 0) {
|
|
@@ -3474,12 +3474,12 @@ async function executeAgent(context, args) {
|
|
|
3474
3474
|
pending = modeResult.rest;
|
|
3475
3475
|
const taskResult = takeOption(pending, "--task");
|
|
3476
3476
|
pending = taskResult.rest;
|
|
3477
|
-
requireNoExtraArgs(pending, "
|
|
3477
|
+
requireNoExtraArgs(pending, "rig agent prepare --task <id> [--id <id>] [--mode worktree]");
|
|
3478
3478
|
const mode = parseIsolationMode(modeResult.value, false);
|
|
3479
3479
|
const id = idResult.value || agentId("agent");
|
|
3480
3480
|
const taskId = taskResult.value?.trim();
|
|
3481
3481
|
if (!taskId) {
|
|
3482
|
-
throw new CliError2("Usage:
|
|
3482
|
+
throw new CliError2("Usage: rig agent prepare --task <id> [--id <id>] [--mode worktree]");
|
|
3483
3483
|
}
|
|
3484
3484
|
const runtime = await withMutedConsole(context.outputMode === "json", () => ensureAgentRuntime({
|
|
3485
3485
|
projectRoot: context.projectRoot,
|
|
@@ -3497,7 +3497,7 @@ async function executeAgent(context, args) {
|
|
|
3497
3497
|
case "run": {
|
|
3498
3498
|
const { options, commandParts } = splitAtDoubleDash(rest);
|
|
3499
3499
|
if (commandParts.length === 0) {
|
|
3500
|
-
throw new CliError2("Usage:
|
|
3500
|
+
throw new CliError2("Usage: rig agent run [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3501
3501
|
}
|
|
3502
3502
|
let pending = options;
|
|
3503
3503
|
const idResult = takeOption(pending, "--id");
|
|
@@ -3508,12 +3508,12 @@ async function executeAgent(context, args) {
|
|
|
3508
3508
|
pending = taskResult.rest;
|
|
3509
3509
|
const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
|
|
3510
3510
|
pending = skipProjectSyncResult.rest;
|
|
3511
|
-
requireNoExtraArgs(pending, "
|
|
3511
|
+
requireNoExtraArgs(pending, "rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3512
3512
|
const mode = parseIsolationMode(modeResult.value, false);
|
|
3513
3513
|
const id = idResult.value || agentId("agent-run");
|
|
3514
3514
|
const taskId = taskResult.value?.trim();
|
|
3515
3515
|
if (!taskId) {
|
|
3516
|
-
throw new CliError2("Usage:
|
|
3516
|
+
throw new CliError2("Usage: rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3517
3517
|
}
|
|
3518
3518
|
await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
|
|
3519
3519
|
const createdAt = new Date().toISOString();
|
|
@@ -3627,7 +3627,7 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
|
|
|
3627
3627
|
pending = allResult.rest;
|
|
3628
3628
|
const idResult = takeOption(pending, "--id");
|
|
3629
3629
|
pending = idResult.rest;
|
|
3630
|
-
requireNoExtraArgs(pending, "
|
|
3630
|
+
requireNoExtraArgs(pending, "rig agent cleanup (--id <id> | --all)");
|
|
3631
3631
|
if (!allResult.value && !idResult.value) {
|
|
3632
3632
|
throw new CliError2("Provide --id <id> or --all.");
|
|
3633
3633
|
}
|
|
@@ -3763,7 +3763,7 @@ async function executeDist(context, args) {
|
|
|
3763
3763
|
switch (command) {
|
|
3764
3764
|
case "build": {
|
|
3765
3765
|
const { value: outputDir, rest: pending } = takeOption(rest, "--output-dir");
|
|
3766
|
-
requireNoExtraArgs(pending, "
|
|
3766
|
+
requireNoExtraArgs(pending, "rig dist build [--output-dir <dir>]");
|
|
3767
3767
|
const commandParts = ["bun", "run", "packages/cli/bin/build-rig-binaries.ts"];
|
|
3768
3768
|
if (outputDir) {
|
|
3769
3769
|
commandParts.push("--output-dir", outputDir);
|
|
@@ -3777,7 +3777,7 @@ async function executeDist(context, args) {
|
|
|
3777
3777
|
pending = scopeResult.rest;
|
|
3778
3778
|
const pathResult = takeOption(pending, "--path");
|
|
3779
3779
|
pending = pathResult.rest;
|
|
3780
|
-
requireNoExtraArgs(pending, "
|
|
3780
|
+
requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
|
|
3781
3781
|
const scope = parseInstallScope(scopeResult.value);
|
|
3782
3782
|
const installDir = resolveInstallDir(scope, pathResult.value);
|
|
3783
3783
|
mkdirSync6(installDir, { recursive: true });
|
|
@@ -3820,7 +3820,7 @@ async function executeDist(context, args) {
|
|
|
3820
3820
|
};
|
|
3821
3821
|
}
|
|
3822
3822
|
case "doctor": {
|
|
3823
|
-
requireNoExtraArgs(rest, "
|
|
3823
|
+
requireNoExtraArgs(rest, "rig dist doctor");
|
|
3824
3824
|
const details = await runDistDoctor(context.projectRoot);
|
|
3825
3825
|
if (context.outputMode === "text") {
|
|
3826
3826
|
console.log(`bun: ${details.bun.available ? `ok (${details.bun.version})` : "missing"}`);
|
|
@@ -3831,7 +3831,7 @@ async function executeDist(context, args) {
|
|
|
3831
3831
|
return { ok: true, group: "dist", command, details };
|
|
3832
3832
|
}
|
|
3833
3833
|
case "rebuild-agent": {
|
|
3834
|
-
requireNoExtraArgs(rest, "
|
|
3834
|
+
requireNoExtraArgs(rest, "rig dist rebuild-agent");
|
|
3835
3835
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
3836
3836
|
const currentId = computeRuntimeImageId(fp);
|
|
3837
3837
|
const imagesDir = resolve12(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
@@ -3983,6 +3983,414 @@ import {
|
|
|
3983
3983
|
readJsonlFile as readJsonlFile3,
|
|
3984
3984
|
resolveAuthorityRunDir as resolveAuthorityRunDir2
|
|
3985
3985
|
} from "@rig/runtime/control-plane/authority-files";
|
|
3986
|
+
|
|
3987
|
+
// packages/cli/src/commands/_cli-format.ts
|
|
3988
|
+
import { log as log3, note as note3 } from "@clack/prompts";
|
|
3989
|
+
import pc3 from "picocolors";
|
|
3990
|
+
function stringField(record, key, fallback = "") {
|
|
3991
|
+
const value = record[key];
|
|
3992
|
+
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
3993
|
+
}
|
|
3994
|
+
function numberField(record, key) {
|
|
3995
|
+
const value = record[key];
|
|
3996
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
3997
|
+
}
|
|
3998
|
+
function arrayField(record, key) {
|
|
3999
|
+
const value = record[key];
|
|
4000
|
+
return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
|
|
4001
|
+
}
|
|
4002
|
+
function rawObject(record) {
|
|
4003
|
+
const raw = record.raw;
|
|
4004
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
4005
|
+
}
|
|
4006
|
+
function truncate(value, width) {
|
|
4007
|
+
if (value.length <= width)
|
|
4008
|
+
return value;
|
|
4009
|
+
if (width <= 1)
|
|
4010
|
+
return "\u2026";
|
|
4011
|
+
return `${value.slice(0, width - 1)}\u2026`;
|
|
4012
|
+
}
|
|
4013
|
+
function pad(value, width) {
|
|
4014
|
+
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
4015
|
+
}
|
|
4016
|
+
function statusColor(status) {
|
|
4017
|
+
const normalized = status.toLowerCase();
|
|
4018
|
+
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
|
|
4019
|
+
return pc3.green;
|
|
4020
|
+
if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
|
|
4021
|
+
return pc3.red;
|
|
4022
|
+
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
4023
|
+
return pc3.cyan;
|
|
4024
|
+
if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
|
|
4025
|
+
return pc3.yellow;
|
|
4026
|
+
return pc3.dim;
|
|
4027
|
+
}
|
|
4028
|
+
function compactDate(value) {
|
|
4029
|
+
if (!value.trim())
|
|
4030
|
+
return "";
|
|
4031
|
+
const parsed = Date.parse(value);
|
|
4032
|
+
if (!Number.isFinite(parsed))
|
|
4033
|
+
return value;
|
|
4034
|
+
return new Date(parsed).toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "Z");
|
|
4035
|
+
}
|
|
4036
|
+
function compactValue(value) {
|
|
4037
|
+
if (value === null || value === undefined)
|
|
4038
|
+
return "";
|
|
4039
|
+
if (typeof value === "string")
|
|
4040
|
+
return value;
|
|
4041
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
4042
|
+
return String(value);
|
|
4043
|
+
if (Array.isArray(value))
|
|
4044
|
+
return value.map(compactValue).filter(Boolean).join(", ");
|
|
4045
|
+
return JSON.stringify(value);
|
|
4046
|
+
}
|
|
4047
|
+
function firstString(record, keys, fallback = "") {
|
|
4048
|
+
for (const key of keys) {
|
|
4049
|
+
const value = stringField(record, key);
|
|
4050
|
+
if (value)
|
|
4051
|
+
return value;
|
|
4052
|
+
}
|
|
4053
|
+
return fallback;
|
|
4054
|
+
}
|
|
4055
|
+
function runIdOf(run) {
|
|
4056
|
+
return firstString(run, ["runId", "id"], "(unknown-run)");
|
|
4057
|
+
}
|
|
4058
|
+
function taskIdOf(run) {
|
|
4059
|
+
return firstString(run, ["taskId", "task", "task_id"]);
|
|
4060
|
+
}
|
|
4061
|
+
function runTitleOf(run) {
|
|
4062
|
+
return firstString(run, ["title", "summary", "name"], taskIdOf(run) || "(untitled)");
|
|
4063
|
+
}
|
|
4064
|
+
function requestIdOf(entry) {
|
|
4065
|
+
return firstString(entry, ["requestId", "id", "approvalId", "inputId"], "(unknown-request)");
|
|
4066
|
+
}
|
|
4067
|
+
function shouldUseClackOutput() {
|
|
4068
|
+
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
4069
|
+
}
|
|
4070
|
+
function printFormattedOutput(message2, options = {}) {
|
|
4071
|
+
if (!shouldUseClackOutput()) {
|
|
4072
|
+
console.log(message2);
|
|
4073
|
+
return;
|
|
4074
|
+
}
|
|
4075
|
+
if (options.title)
|
|
4076
|
+
note3(message2, options.title);
|
|
4077
|
+
else
|
|
4078
|
+
log3.message(message2);
|
|
4079
|
+
}
|
|
4080
|
+
function formatStatusPill(status) {
|
|
4081
|
+
const label = status || "unknown";
|
|
4082
|
+
return statusColor(label)(`\u25CF ${label}`);
|
|
4083
|
+
}
|
|
4084
|
+
function formatSection(title, subtitle) {
|
|
4085
|
+
return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
4086
|
+
}
|
|
4087
|
+
function formatSuccessCard(title, rows = []) {
|
|
4088
|
+
const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc3.dim("\u2502")} ${pc3.dim(key.padEnd(12))} ${value}`);
|
|
4089
|
+
return [formatSection(title), ...body].join(`
|
|
4090
|
+
`);
|
|
4091
|
+
}
|
|
4092
|
+
function formatNextSteps(steps) {
|
|
4093
|
+
if (steps.length === 0)
|
|
4094
|
+
return [];
|
|
4095
|
+
return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
|
|
4096
|
+
}
|
|
4097
|
+
function formatTaskList(tasks, options = {}) {
|
|
4098
|
+
if (options.raw)
|
|
4099
|
+
return tasks.map((task) => JSON.stringify(task)).join(`
|
|
4100
|
+
`);
|
|
4101
|
+
if (tasks.length === 0)
|
|
4102
|
+
return [formatSection("Tasks", "none found"), ...formatNextSteps(["Try `rig server status` to confirm the selected server.", "Relax filters or run `rig task run --title ... --initial-prompt ...` for ad hoc work."])].join(`
|
|
4103
|
+
`);
|
|
4104
|
+
const rows = tasks.map((task) => {
|
|
4105
|
+
const raw = rawObject(task);
|
|
4106
|
+
const id = stringField(task, "id", "<unknown>");
|
|
4107
|
+
const status = stringField(task, "status", "unknown");
|
|
4108
|
+
const title = stringField(task, "title", "Untitled task");
|
|
4109
|
+
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
4110
|
+
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
4111
|
+
return { id, status, title, source, labels };
|
|
4112
|
+
});
|
|
4113
|
+
const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
|
|
4114
|
+
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
4115
|
+
const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
4116
|
+
const body = rows.map((row) => {
|
|
4117
|
+
const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
|
|
4118
|
+
const source = row.source ? pc3.dim(` ${row.source}`) : "";
|
|
4119
|
+
return [
|
|
4120
|
+
pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
|
|
4121
|
+
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
4122
|
+
`${row.title}${labels}${source}`
|
|
4123
|
+
].join(" ");
|
|
4124
|
+
});
|
|
4125
|
+
return [formatSection("Tasks", `${rows.length} shown`), header, ...body, "", ...formatNextSteps(["Run one: `rig task run <id>` or `rig task run --next`", "Attach later: `rig run attach <run-id> --follow`"])].join(`
|
|
4126
|
+
`);
|
|
4127
|
+
}
|
|
4128
|
+
function formatTaskCard(task, options = {}) {
|
|
4129
|
+
const raw = rawObject(task);
|
|
4130
|
+
const id = stringField(task, "id", stringField(raw, "id", "<unknown>"));
|
|
4131
|
+
const status = stringField(task, "status", stringField(raw, "status", "unknown"));
|
|
4132
|
+
const title = stringField(task, "title", stringField(raw, "title", "Untitled task"));
|
|
4133
|
+
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
4134
|
+
const url = stringField(task, "url", stringField(raw, "url", ""));
|
|
4135
|
+
const number = numberField(task, "number") ?? numberField(raw, "number");
|
|
4136
|
+
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
4137
|
+
const assignees = arrayField(task, "assignees").length > 0 ? arrayField(task, "assignees") : arrayField(raw, "assignees");
|
|
4138
|
+
const readiness = compactValue(task.readiness ?? raw.readiness);
|
|
4139
|
+
const validators = compactValue(task.validators ?? raw.validators ?? task.validation ?? raw.validation);
|
|
4140
|
+
const rows = [
|
|
4141
|
+
["task", pc3.bold(id)],
|
|
4142
|
+
["status", formatStatusPill(status)],
|
|
4143
|
+
["title", title],
|
|
4144
|
+
["source", source],
|
|
4145
|
+
["number", number],
|
|
4146
|
+
["labels", labels.length ? labels.map((label) => `#${label}`).join(" ") : ""],
|
|
4147
|
+
["assignees", assignees.join(", ")],
|
|
4148
|
+
["readiness", readiness],
|
|
4149
|
+
["validators", validators],
|
|
4150
|
+
["url", url]
|
|
4151
|
+
];
|
|
4152
|
+
return [
|
|
4153
|
+
formatSuccessCard(options.title ?? (options.selected ? "Selected task" : "Task"), rows),
|
|
4154
|
+
"",
|
|
4155
|
+
...formatNextSteps([`Start: \`rig task run ${id}\``, `Details: \`rig task show ${id} --raw\``])
|
|
4156
|
+
].join(`
|
|
4157
|
+
`);
|
|
4158
|
+
}
|
|
4159
|
+
function formatTaskDetails(task) {
|
|
4160
|
+
return formatTaskCard(task, { title: "Task details" });
|
|
4161
|
+
}
|
|
4162
|
+
function formatRunList(runs, options = {}) {
|
|
4163
|
+
if (runs.length === 0) {
|
|
4164
|
+
return [
|
|
4165
|
+
formatSection("Runs", "none recorded"),
|
|
4166
|
+
options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
|
|
4167
|
+
"",
|
|
4168
|
+
...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
|
|
4169
|
+
].join(`
|
|
4170
|
+
`);
|
|
4171
|
+
}
|
|
4172
|
+
const rows = runs.map((run) => {
|
|
4173
|
+
const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
|
|
4174
|
+
const status = stringField(run, "status", "unknown");
|
|
4175
|
+
const taskId = stringField(run, "taskId", "");
|
|
4176
|
+
const title = stringField(run, "title", taskId || "(untitled)");
|
|
4177
|
+
const runtime = stringField(run, "runtimeAdapter", "");
|
|
4178
|
+
return { runId, status, title, runtime };
|
|
4179
|
+
});
|
|
4180
|
+
const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
|
|
4181
|
+
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
4182
|
+
const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
4183
|
+
const body = rows.map((row) => [
|
|
4184
|
+
pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
|
|
4185
|
+
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
4186
|
+
`${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
|
|
4187
|
+
].join(" "));
|
|
4188
|
+
return [formatSection("Runs", options.source === "server" ? "selected server" : "local state"), header, ...body, "", ...formatNextSteps(["Follow live: `rig run attach <run-id> --follow`", "Details: `rig run show <run-id>`"])].join(`
|
|
4189
|
+
`);
|
|
4190
|
+
}
|
|
4191
|
+
function formatSubmittedRun(input) {
|
|
4192
|
+
const rows = [["run", pc3.bold(input.runId)]];
|
|
4193
|
+
if (input.task) {
|
|
4194
|
+
const id = stringField(input.task, "id", "<unknown>");
|
|
4195
|
+
const status = stringField(input.task, "status", "unknown");
|
|
4196
|
+
const title = stringField(input.task, "title", "Untitled task");
|
|
4197
|
+
rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
|
|
4198
|
+
}
|
|
4199
|
+
const runtime = [input.runtimeAdapter || "pi", input.runtimeMode || "full-access", input.interactionMode || "default"].filter(Boolean).join(" \xB7 ");
|
|
4200
|
+
rows.push(["runtime", runtime]);
|
|
4201
|
+
return [
|
|
4202
|
+
formatSuccessCard("Run submitted", rows),
|
|
4203
|
+
"",
|
|
4204
|
+
...formatNextSteps([
|
|
4205
|
+
`Attach: \`rig run attach ${input.runId} --follow\``,
|
|
4206
|
+
`Inspect: \`rig run show ${input.runId}\``,
|
|
4207
|
+
input.detached ? "Submitted detached; attach when you are ready." : "Interactive mode opens the native bundled Pi frontend."
|
|
4208
|
+
])
|
|
4209
|
+
].join(`
|
|
4210
|
+
`);
|
|
4211
|
+
}
|
|
4212
|
+
function formatRunCard(run, options = {}) {
|
|
4213
|
+
const raw = rawObject(run);
|
|
4214
|
+
const merged = { ...raw, ...run };
|
|
4215
|
+
const runId = runIdOf(merged);
|
|
4216
|
+
const status = firstString(merged, ["status"], "unknown");
|
|
4217
|
+
const taskId = taskIdOf(merged);
|
|
4218
|
+
const title = runTitleOf(merged);
|
|
4219
|
+
const runtime = firstString(merged, ["runtimeAdapter", "runtime", "adapter"]);
|
|
4220
|
+
const mode = firstString(merged, ["runtimeMode", "mode"]);
|
|
4221
|
+
const interaction = firstString(merged, ["interactionMode"]);
|
|
4222
|
+
const created = compactDate(firstString(merged, ["createdAt"]));
|
|
4223
|
+
const started = compactDate(firstString(merged, ["startedAt"]));
|
|
4224
|
+
const updated = compactDate(firstString(merged, ["updatedAt"]));
|
|
4225
|
+
const completed = compactDate(firstString(merged, ["completedAt", "finishedAt"]));
|
|
4226
|
+
const worktree = firstString(merged, ["worktreePath", "cwd", "projectRoot"]);
|
|
4227
|
+
const piSession = merged.piSession && typeof merged.piSession === "object" && !Array.isArray(merged.piSession) ? firstString(merged.piSession, ["sessionId", "id"]) : "";
|
|
4228
|
+
const timeline = Array.isArray(merged.timeline) ? merged.timeline.length : null;
|
|
4229
|
+
const approvals = Array.isArray(merged.approvals) ? merged.approvals.length : null;
|
|
4230
|
+
const inputs = Array.isArray(merged.userInputs) ? merged.userInputs.length : null;
|
|
4231
|
+
const rows = [
|
|
4232
|
+
["run", pc3.bold(runId)],
|
|
4233
|
+
["status", formatStatusPill(status)],
|
|
4234
|
+
["task", taskId],
|
|
4235
|
+
["title", title],
|
|
4236
|
+
["runtime", [runtime, mode, interaction].filter(Boolean).join(" \xB7 ")],
|
|
4237
|
+
["created", created],
|
|
4238
|
+
["started", started],
|
|
4239
|
+
["updated", updated],
|
|
4240
|
+
["completed", completed],
|
|
4241
|
+
["worktree", worktree],
|
|
4242
|
+
["pi", piSession],
|
|
4243
|
+
["timeline", timeline],
|
|
4244
|
+
["approvals", approvals],
|
|
4245
|
+
["inputs", inputs]
|
|
4246
|
+
];
|
|
4247
|
+
return [
|
|
4248
|
+
formatSuccessCard(options.title ?? "Run details", rows),
|
|
4249
|
+
"",
|
|
4250
|
+
...formatNextSteps([`Follow live: \`rig run attach ${runId} --follow\``, `Raw payload: \`rig run show ${runId} --raw\``])
|
|
4251
|
+
].join(`
|
|
4252
|
+
`);
|
|
4253
|
+
}
|
|
4254
|
+
function formatRunStatus(summary, options = {}) {
|
|
4255
|
+
const activeRuns = summary.activeRuns ?? [];
|
|
4256
|
+
const recentRuns = summary.recentRuns ?? [];
|
|
4257
|
+
const lines = [formatSection("Run status", options.source === "server" ? "selected server" : "local state")];
|
|
4258
|
+
lines.push("", pc3.bold(`Active runs (${activeRuns.length})`));
|
|
4259
|
+
if (activeRuns.length === 0) {
|
|
4260
|
+
lines.push(pc3.dim("No active runs."));
|
|
4261
|
+
} else {
|
|
4262
|
+
for (const run of activeRuns) {
|
|
4263
|
+
lines.push(formatRunSummaryLine(run));
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
lines.push("", pc3.bold(`Recent runs (${recentRuns.length})`));
|
|
4267
|
+
if (recentRuns.length === 0) {
|
|
4268
|
+
lines.push(pc3.dim("No recent terminal runs."));
|
|
4269
|
+
} else {
|
|
4270
|
+
for (const run of recentRuns.slice(0, 10)) {
|
|
4271
|
+
lines.push(formatRunSummaryLine(run));
|
|
4272
|
+
}
|
|
4273
|
+
}
|
|
4274
|
+
lines.push("", ...formatNextSteps(["Start work: `rig task run --next`", "Attach: `rig run attach <run-id> --follow`", "Details: `rig run show <run-id>`"]));
|
|
4275
|
+
return lines.join(`
|
|
4276
|
+
`);
|
|
4277
|
+
}
|
|
4278
|
+
function formatRunSummaryLine(run) {
|
|
4279
|
+
const record = run;
|
|
4280
|
+
const runId = runIdOf(record);
|
|
4281
|
+
const status = firstString(record, ["status"], "unknown");
|
|
4282
|
+
const taskId = taskIdOf(record);
|
|
4283
|
+
const title = runTitleOf(record);
|
|
4284
|
+
const runtime = firstString(record, ["runtimeAdapter", "runtime", "adapter"]);
|
|
4285
|
+
const descriptor = [taskId, title].filter(Boolean).join(" \xB7 ");
|
|
4286
|
+
return `${pc3.dim("\u2502")} ${pc3.bold(runId)} ${formatStatusPill(status)} ${descriptor}${runtime ? pc3.dim(` ${runtime}`) : ""}`;
|
|
4287
|
+
}
|
|
4288
|
+
function formatInboxList(kind, entries) {
|
|
4289
|
+
const title = kind === "approvals" ? "Approval inbox" : "Input inbox";
|
|
4290
|
+
if (entries.length === 0) {
|
|
4291
|
+
return [
|
|
4292
|
+
formatSection(title, "empty"),
|
|
4293
|
+
pc3.dim(kind === "approvals" ? "No pending approvals." : "No pending user-input requests."),
|
|
4294
|
+
"",
|
|
4295
|
+
...formatNextSteps(["Check runs: `rig run status`", "Start work: `rig task run --next`"])
|
|
4296
|
+
].join(`
|
|
4297
|
+
`);
|
|
4298
|
+
}
|
|
4299
|
+
const lines = [formatSection(title, `${entries.length} pending`)];
|
|
4300
|
+
for (const entry of entries) {
|
|
4301
|
+
const record = entry.record && typeof entry.record === "object" && !Array.isArray(entry.record) ? entry.record : entry;
|
|
4302
|
+
const runId = firstString(entry, ["runId"], firstString(record, ["runId"]));
|
|
4303
|
+
const taskId = firstString(entry, ["taskId"], firstString(record, ["taskId", "task"]));
|
|
4304
|
+
const requestId = requestIdOf(record);
|
|
4305
|
+
const status = firstString(record, ["status", "state"], "pending");
|
|
4306
|
+
const prompt = firstString(record, ["prompt", "message", "reason", "title", "summary"], kind === "approvals" ? "Approval requested" : "Input requested");
|
|
4307
|
+
lines.push(`${pc3.dim("\u2502")} ${pc3.bold(requestId)} ${formatStatusPill(status)} ${prompt}`);
|
|
4308
|
+
lines.push(`${pc3.dim("\u2502")} ${pc3.dim("run ")} ${runId || "(unknown-run)"}${taskId ? pc3.dim(` task ${taskId}`) : ""}`);
|
|
4309
|
+
}
|
|
4310
|
+
lines.push("", ...formatNextSteps(kind === "approvals" ? ["Resolve: `rig inbox approve --run <run-id> --request <request-id> --decision approve|reject`", "Rejoin: `rig run attach <run-id> --follow`"] : ["Respond: `rig inbox respond --run <run-id> --request <request-id> --answer key=value`", "Rejoin: `rig run attach <run-id> --follow`"]));
|
|
4311
|
+
return lines.join(`
|
|
4312
|
+
`);
|
|
4313
|
+
}
|
|
4314
|
+
function formatConnectionList(connections) {
|
|
4315
|
+
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
4316
|
+
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
4317
|
+
const lines = rows.map(([alias, connection]) => [
|
|
4318
|
+
pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
4319
|
+
formatStatusPill(connection.kind),
|
|
4320
|
+
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
4321
|
+
].join(" "));
|
|
4322
|
+
return [formatSection("Rig servers", `${rows.length} available`), `${pc3.bold(pad("ALIAS", aliasWidth))} ${pc3.bold("KIND")} ${pc3.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
|
|
4323
|
+
`);
|
|
4324
|
+
}
|
|
4325
|
+
function formatConnectionStatus(selected, connections) {
|
|
4326
|
+
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
4327
|
+
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
4328
|
+
return [
|
|
4329
|
+
formatSection("Rig server", "selected for this repo"),
|
|
4330
|
+
`${pc3.dim("\u2502")} ${pc3.dim("selected ")} ${pc3.bold(selected)}`,
|
|
4331
|
+
`${pc3.dim("\u2502")} ${pc3.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
4332
|
+
`${pc3.dim("\u2502")} ${pc3.dim("target ")} ${target ?? "not configured"}`,
|
|
4333
|
+
"",
|
|
4334
|
+
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
4335
|
+
].join(`
|
|
4336
|
+
`);
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
// packages/cli/src/commands/inbox.ts
|
|
4340
|
+
function isRemoteConnectionSelected(projectRoot) {
|
|
4341
|
+
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
4342
|
+
}
|
|
4343
|
+
function runMatches(entry, filters) {
|
|
4344
|
+
const runId = typeof entry.runId === "string" ? entry.runId : typeof entry.id === "string" ? entry.id : "";
|
|
4345
|
+
const taskId = typeof entry.taskId === "string" ? entry.taskId : "";
|
|
4346
|
+
return (!filters.run || runId === filters.run) && (!filters.task || taskId === filters.task);
|
|
4347
|
+
}
|
|
4348
|
+
function normalizeRemoteRunDetails(payload) {
|
|
4349
|
+
const run = payload.run;
|
|
4350
|
+
if (run && typeof run === "object" && !Array.isArray(run)) {
|
|
4351
|
+
return {
|
|
4352
|
+
...run,
|
|
4353
|
+
...Array.isArray(payload.timeline) ? { timeline: payload.timeline } : {},
|
|
4354
|
+
...Array.isArray(payload.approvals) ? { approvals: payload.approvals } : {},
|
|
4355
|
+
...Array.isArray(payload.userInputs) ? { userInputs: payload.userInputs } : {}
|
|
4356
|
+
};
|
|
4357
|
+
}
|
|
4358
|
+
return payload;
|
|
4359
|
+
}
|
|
4360
|
+
function remoteRecordsFromRun(run, kind) {
|
|
4361
|
+
const key = kind === "approvals" ? "approvals" : "userInputs";
|
|
4362
|
+
const direct = run[key];
|
|
4363
|
+
if (!Array.isArray(direct))
|
|
4364
|
+
return [];
|
|
4365
|
+
const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
|
|
4366
|
+
const taskId = typeof run.taskId === "string" ? run.taskId : "";
|
|
4367
|
+
return direct.filter((record) => Boolean(record && typeof record === "object" && !Array.isArray(record))).map((record) => ({ runId, taskId, record }));
|
|
4368
|
+
}
|
|
4369
|
+
async function listRemoteInboxRecords(context, kind, filters) {
|
|
4370
|
+
const runs = (await listRunsViaServer(context, { limit: 100 })).filter((entry) => runMatches(entry, filters));
|
|
4371
|
+
const records = [];
|
|
4372
|
+
for (const run of runs) {
|
|
4373
|
+
const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
|
|
4374
|
+
const detailed = runId ? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => run)) : run;
|
|
4375
|
+
records.push(...remoteRecordsFromRun(detailed, kind));
|
|
4376
|
+
}
|
|
4377
|
+
return records;
|
|
4378
|
+
}
|
|
4379
|
+
function listLocalInboxRecords(context, kind, filters) {
|
|
4380
|
+
const fileName = kind === "approvals" ? "approvals.jsonl" : "user-input.jsonl";
|
|
4381
|
+
const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!filters.run || entry.runId === filters.run) && (!filters.task || entry.taskId === filters.task));
|
|
4382
|
+
return runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), fileName)).map((record) => ({
|
|
4383
|
+
runId: entry.runId,
|
|
4384
|
+
taskId: entry.taskId ?? undefined,
|
|
4385
|
+
record
|
|
4386
|
+
})));
|
|
4387
|
+
}
|
|
4388
|
+
async function listInboxRecords(context, kind, filters) {
|
|
4389
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4390
|
+
return listRemoteInboxRecords(context, kind, filters);
|
|
4391
|
+
}
|
|
4392
|
+
return listLocalInboxRecords(context, kind, filters);
|
|
4393
|
+
}
|
|
3986
4394
|
async function executeInbox(context, args) {
|
|
3987
4395
|
const [command = "approvals", ...rest] = args;
|
|
3988
4396
|
switch (command) {
|
|
@@ -3992,16 +4400,10 @@ async function executeInbox(context, args) {
|
|
|
3992
4400
|
pending = run.rest;
|
|
3993
4401
|
const task = takeOption(pending, "--task");
|
|
3994
4402
|
pending = task.rest;
|
|
3995
|
-
requireNoExtraArgs(pending, "
|
|
3996
|
-
const
|
|
3997
|
-
const approvals = runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "approvals.jsonl")).map((record) => ({
|
|
3998
|
-
runId: entry.runId,
|
|
3999
|
-
record
|
|
4000
|
-
})));
|
|
4403
|
+
requireNoExtraArgs(pending, "rig inbox approvals [--run <id>] [--task <id>]");
|
|
4404
|
+
const approvals = await listInboxRecords(context, "approvals", { run: run.value, task: task.value });
|
|
4001
4405
|
if (context.outputMode === "text") {
|
|
4002
|
-
|
|
4003
|
-
console.log(JSON.stringify(approval));
|
|
4004
|
-
}
|
|
4406
|
+
printFormattedOutput(formatInboxList("approvals", approvals));
|
|
4005
4407
|
}
|
|
4006
4408
|
return { ok: true, group: "inbox", command, details: { approvals } };
|
|
4007
4409
|
}
|
|
@@ -4013,19 +4415,22 @@ async function executeInbox(context, args) {
|
|
|
4013
4415
|
pending = request.rest;
|
|
4014
4416
|
const decision = takeOption(pending, "--decision");
|
|
4015
4417
|
pending = decision.rest;
|
|
4016
|
-
const
|
|
4017
|
-
pending =
|
|
4018
|
-
requireNoExtraArgs(pending, "
|
|
4418
|
+
const note4 = takeOption(pending, "--note");
|
|
4419
|
+
pending = note4.rest;
|
|
4420
|
+
requireNoExtraArgs(pending, "rig inbox approve --run <id> --request <id> --decision approve|reject [--note <text>]");
|
|
4019
4421
|
if (!run.value || !request.value || !decision.value) {
|
|
4020
4422
|
throw new CliError2("approve requires --run, --request, and --decision.");
|
|
4021
4423
|
}
|
|
4022
4424
|
if (decision.value !== "approve" && decision.value !== "reject") {
|
|
4023
4425
|
throw new CliError2("decision must be approve or reject.");
|
|
4024
4426
|
}
|
|
4427
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4428
|
+
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);
|
|
4429
|
+
}
|
|
4025
4430
|
const approvalsPath = resolve13(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
|
|
4026
4431
|
const approvals = readJsonlFile3(approvalsPath);
|
|
4027
4432
|
const resolvedAt = new Date().toISOString();
|
|
4028
|
-
const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note:
|
|
4433
|
+
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);
|
|
4029
4434
|
writeFileSync4(approvalsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
|
|
4030
4435
|
`)}
|
|
4031
4436
|
`, "utf8");
|
|
@@ -4037,16 +4442,10 @@ async function executeInbox(context, args) {
|
|
|
4037
4442
|
pending = run.rest;
|
|
4038
4443
|
const task = takeOption(pending, "--task");
|
|
4039
4444
|
pending = task.rest;
|
|
4040
|
-
requireNoExtraArgs(pending, "
|
|
4041
|
-
const
|
|
4042
|
-
const requests = runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "user-input.jsonl")).map((record) => ({
|
|
4043
|
-
runId: entry.runId,
|
|
4044
|
-
record
|
|
4045
|
-
})));
|
|
4445
|
+
requireNoExtraArgs(pending, "rig inbox inputs [--run <id>] [--task <id>]");
|
|
4446
|
+
const requests = await listInboxRecords(context, "inputs", { run: run.value, task: task.value });
|
|
4046
4447
|
if (context.outputMode === "text") {
|
|
4047
|
-
|
|
4048
|
-
console.log(JSON.stringify(request));
|
|
4049
|
-
}
|
|
4448
|
+
printFormattedOutput(formatInboxList("inputs", requests));
|
|
4050
4449
|
}
|
|
4051
4450
|
return { ok: true, group: "inbox", command, details: { requests } };
|
|
4052
4451
|
}
|
|
@@ -4073,10 +4472,13 @@ async function executeInbox(context, args) {
|
|
|
4073
4472
|
remaining.push(current);
|
|
4074
4473
|
}
|
|
4075
4474
|
}
|
|
4076
|
-
requireNoExtraArgs(remaining, "
|
|
4475
|
+
requireNoExtraArgs(remaining, "rig inbox respond --run <id> --request <id> --answer key=value [--answer key=value]");
|
|
4077
4476
|
if (!run.value || !request.value || answers.length === 0) {
|
|
4078
4477
|
throw new CliError2("respond requires --run, --request, and at least one --answer.");
|
|
4079
4478
|
}
|
|
4479
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4480
|
+
throw new CliError2("Remote input responses are not available from this CLI yet; use the server UI/API or switch to local state for direct JSONL edits.", 2);
|
|
4481
|
+
}
|
|
4080
4482
|
const parsedAnswers = Object.fromEntries(answers.map((entry) => {
|
|
4081
4483
|
const [key, ...restValue] = entry.split("=");
|
|
4082
4484
|
return [key, restValue.join("=")];
|
|
@@ -4500,7 +4902,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4500
4902
|
const taskSourceKind = config?.taskSource?.kind;
|
|
4501
4903
|
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."));
|
|
4502
4904
|
const repo = readRepoConnection(projectRoot);
|
|
4503
|
-
checks.push(repo ? check("project-link", "repo selected Rig
|
|
4905
|
+
checks.push(repo ? check("project-link", "repo selected Rig server", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to link this checkout to a GitHub repo slug.") : check("project-link", "repo selected Rig server", "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
|
|
4504
4906
|
const selected = (() => {
|
|
4505
4907
|
try {
|
|
4506
4908
|
return resolveSelectedConnection(projectRoot);
|
|
@@ -4508,7 +4910,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4508
4910
|
return null;
|
|
4509
4911
|
}
|
|
4510
4912
|
})();
|
|
4511
|
-
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server
|
|
4913
|
+
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server", repo ? "fail" : "warn", repo ? "selected alias is missing" : "will auto-start local server", repo ? "Run `rig server list` and `rig server use <alias|local>`." : undefined));
|
|
4512
4914
|
let server = null;
|
|
4513
4915
|
try {
|
|
4514
4916
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
@@ -5291,187 +5693,32 @@ async function runInteractiveControlPlaneInit(context, prompts) {
|
|
|
5291
5693
|
githubProjectStatusField: projectConfig.githubProjectStatusField,
|
|
5292
5694
|
githubProjectStatuses: projectConfig.githubProjectStatuses,
|
|
5293
5695
|
remoteCheckout,
|
|
5294
|
-
repair,
|
|
5295
|
-
privateStateOnly,
|
|
5296
|
-
yes: remoteGhTokenConfirmed || undefined
|
|
5297
|
-
});
|
|
5298
|
-
const details = result.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : {};
|
|
5299
|
-
const deviceAuth = details.deviceAuth && typeof details.deviceAuth === "object" && !Array.isArray(details.deviceAuth) ? details.deviceAuth : null;
|
|
5300
|
-
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")}.` : "";
|
|
5301
|
-
prompts.outro?.(`Rig project initialized.${deviceMessage} Next: rig doctor && rig task list`);
|
|
5302
|
-
return result;
|
|
5303
|
-
}
|
|
5304
|
-
async function executeInit(context, args) {
|
|
5305
|
-
const parsed = parseInitOptions(args);
|
|
5306
|
-
if (parsed.options.yes || parsed.options.server || parsed.options.repoSlug || parsed.options.githubToken || parsed.options.privateStateOnly || parsed.options.repair || parsed.options.githubAuthMethod || parsed.options.remoteCheckout) {
|
|
5307
|
-
if (parsed.rest.length > 0)
|
|
5308
|
-
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5309
|
-
Usage: rig init [--server local|remote] [--remote-url <url>] [--repo owner/repo] [--github-auth gh|token|device|skip] [--github-token <token>] [--github-project off|<project-id>] [--remote-checkout managed-clone|current-ref|uploaded-snapshot|existing-path] [--yes]`, 1);
|
|
5310
|
-
return runControlPlaneInit(context, parsed.options);
|
|
5311
|
-
}
|
|
5312
|
-
if (parsed.rest.length > 0)
|
|
5313
|
-
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5314
|
-
Usage: rig init`, 1);
|
|
5315
|
-
return runInteractiveControlPlaneInit(context, await loadClackPrompts());
|
|
5316
|
-
}
|
|
5317
|
-
|
|
5318
|
-
// packages/cli/src/commands/connect.ts
|
|
5319
|
-
import { cancel as cancel2, isCancel as isCancel2, select as select2 } from "@clack/prompts";
|
|
5320
|
-
|
|
5321
|
-
// packages/cli/src/commands/_cli-format.ts
|
|
5322
|
-
import pc3 from "picocolors";
|
|
5323
|
-
function stringField(record, key, fallback = "") {
|
|
5324
|
-
const value = record[key];
|
|
5325
|
-
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
5326
|
-
}
|
|
5327
|
-
function arrayField(record, key) {
|
|
5328
|
-
const value = record[key];
|
|
5329
|
-
return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
|
|
5330
|
-
}
|
|
5331
|
-
function rawObject(record) {
|
|
5332
|
-
const raw = record.raw;
|
|
5333
|
-
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
5334
|
-
}
|
|
5335
|
-
function truncate(value, width) {
|
|
5336
|
-
if (value.length <= width)
|
|
5337
|
-
return value;
|
|
5338
|
-
if (width <= 1)
|
|
5339
|
-
return "\u2026";
|
|
5340
|
-
return `${value.slice(0, width - 1)}\u2026`;
|
|
5341
|
-
}
|
|
5342
|
-
function pad(value, width) {
|
|
5343
|
-
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
5344
|
-
}
|
|
5345
|
-
function statusColor(status) {
|
|
5346
|
-
const normalized = status.toLowerCase();
|
|
5347
|
-
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected"].includes(normalized))
|
|
5348
|
-
return pc3.green;
|
|
5349
|
-
if (["failed", "needs_attention", "needs-attention", "blocked", "error"].includes(normalized))
|
|
5350
|
-
return pc3.red;
|
|
5351
|
-
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
5352
|
-
return pc3.cyan;
|
|
5353
|
-
if (["ready", "open", "queued", "created", "preparing", "local"].includes(normalized))
|
|
5354
|
-
return pc3.yellow;
|
|
5355
|
-
return pc3.dim;
|
|
5356
|
-
}
|
|
5357
|
-
function formatStatusPill(status) {
|
|
5358
|
-
const label = status || "unknown";
|
|
5359
|
-
return statusColor(label)(`\u25CF ${label}`);
|
|
5360
|
-
}
|
|
5361
|
-
function formatSection(title, subtitle) {
|
|
5362
|
-
return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
5363
|
-
}
|
|
5364
|
-
function formatSuccessCard(title, rows = []) {
|
|
5365
|
-
const body = rows.filter(([, value]) => value !== undefined && value !== null && String(value).length > 0).map(([key, value]) => `${pc3.dim("\u2502")} ${pc3.dim(key.padEnd(9))} ${value}`);
|
|
5366
|
-
return [formatSection(title), ...body].join(`
|
|
5367
|
-
`);
|
|
5368
|
-
}
|
|
5369
|
-
function formatNextSteps(steps) {
|
|
5370
|
-
if (steps.length === 0)
|
|
5371
|
-
return [];
|
|
5372
|
-
return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
|
|
5373
|
-
}
|
|
5374
|
-
function formatTaskList(tasks, options = {}) {
|
|
5375
|
-
if (options.raw)
|
|
5376
|
-
return tasks.map((task) => JSON.stringify(task)).join(`
|
|
5377
|
-
`);
|
|
5378
|
-
if (tasks.length === 0)
|
|
5379
|
-
return [formatSection("Tasks", "none found"), ...formatNextSteps(["Try `rig server status` to confirm the selected server.", "Relax filters or run `rig task run --title ... --initial-prompt ...` for ad hoc work."])].join(`
|
|
5380
|
-
`);
|
|
5381
|
-
const rows = tasks.map((task) => {
|
|
5382
|
-
const raw = rawObject(task);
|
|
5383
|
-
const id = stringField(task, "id", "<unknown>");
|
|
5384
|
-
const status = stringField(task, "status", "unknown");
|
|
5385
|
-
const title = stringField(task, "title", "Untitled task");
|
|
5386
|
-
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
5387
|
-
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
5388
|
-
return { id, status, title, source, labels };
|
|
5389
|
-
});
|
|
5390
|
-
const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
|
|
5391
|
-
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
5392
|
-
const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
5393
|
-
const body = rows.map((row) => {
|
|
5394
|
-
const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
|
|
5395
|
-
const source = row.source ? pc3.dim(` ${row.source}`) : "";
|
|
5396
|
-
return [
|
|
5397
|
-
pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
|
|
5398
|
-
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
5399
|
-
`${row.title}${labels}${source}`
|
|
5400
|
-
].join(" ");
|
|
5401
|
-
});
|
|
5402
|
-
return [formatSection("Tasks", `${rows.length} shown`), header, ...body, "", ...formatNextSteps(["Run one: `rig task run <id>` or `rig task run --next`", "Attach later: `rig run attach <run-id> --follow`"])].join(`
|
|
5403
|
-
`);
|
|
5404
|
-
}
|
|
5405
|
-
function formatRunList(runs, options = {}) {
|
|
5406
|
-
if (runs.length === 0) {
|
|
5407
|
-
return [
|
|
5408
|
-
formatSection("Runs", "none recorded"),
|
|
5409
|
-
options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
|
|
5410
|
-
"",
|
|
5411
|
-
...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
|
|
5412
|
-
].join(`
|
|
5413
|
-
`);
|
|
5414
|
-
}
|
|
5415
|
-
const rows = runs.map((run) => {
|
|
5416
|
-
const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
|
|
5417
|
-
const status = stringField(run, "status", "unknown");
|
|
5418
|
-
const taskId = stringField(run, "taskId", "");
|
|
5419
|
-
const title = stringField(run, "title", taskId || "(untitled)");
|
|
5420
|
-
const runtime = stringField(run, "runtimeAdapter", "");
|
|
5421
|
-
return { runId, status, title, runtime };
|
|
5422
|
-
});
|
|
5423
|
-
const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
|
|
5424
|
-
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
5425
|
-
const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
5426
|
-
const body = rows.map((row) => [
|
|
5427
|
-
pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
|
|
5428
|
-
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
5429
|
-
`${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
|
|
5430
|
-
].join(" "));
|
|
5431
|
-
return [formatSection("Runs", options.source === "server" ? "selected server" : "local state"), header, ...body, "", ...formatNextSteps(["Follow live: `rig run attach <run-id> --follow`", "Details: `rig run show --run <run-id>`"])].join(`
|
|
5432
|
-
`);
|
|
5433
|
-
}
|
|
5434
|
-
function formatSubmittedRun(input) {
|
|
5435
|
-
const rows = [["run", pc3.bold(input.runId)]];
|
|
5436
|
-
if (input.task) {
|
|
5437
|
-
const id = stringField(input.task, "id", "<unknown>");
|
|
5438
|
-
const status = stringField(input.task, "status", "unknown");
|
|
5439
|
-
const title = stringField(input.task, "title", "Untitled task");
|
|
5440
|
-
rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
|
|
5441
|
-
}
|
|
5442
|
-
return [
|
|
5443
|
-
formatSuccessCard("Run submitted", rows),
|
|
5444
|
-
"",
|
|
5445
|
-
...formatNextSteps([`Attach: \`rig run attach ${input.runId} --follow\``, `Inspect: \`rig run show --run ${input.runId}\``])
|
|
5446
|
-
].join(`
|
|
5447
|
-
`);
|
|
5448
|
-
}
|
|
5449
|
-
function formatConnectionList(connections) {
|
|
5450
|
-
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
5451
|
-
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
5452
|
-
const lines = rows.map(([alias, connection]) => [
|
|
5453
|
-
pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
5454
|
-
formatStatusPill(connection.kind),
|
|
5455
|
-
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
5456
|
-
].join(" "));
|
|
5457
|
-
return [formatSection("Rig servers", `${rows.length} available`), `${pc3.bold(pad("ALIAS", aliasWidth))} ${pc3.bold("KIND")} ${pc3.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
|
|
5458
|
-
`);
|
|
5696
|
+
repair,
|
|
5697
|
+
privateStateOnly,
|
|
5698
|
+
yes: remoteGhTokenConfirmed || undefined
|
|
5699
|
+
});
|
|
5700
|
+
const details = result.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : {};
|
|
5701
|
+
const deviceAuth = details.deviceAuth && typeof details.deviceAuth === "object" && !Array.isArray(details.deviceAuth) ? details.deviceAuth : null;
|
|
5702
|
+
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")}.` : "";
|
|
5703
|
+
prompts.outro?.(`Rig project initialized.${deviceMessage} Next: rig doctor && rig task list`);
|
|
5704
|
+
return result;
|
|
5459
5705
|
}
|
|
5460
|
-
function
|
|
5461
|
-
const
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5469
|
-
|
|
5470
|
-
|
|
5471
|
-
|
|
5706
|
+
async function executeInit(context, args) {
|
|
5707
|
+
const parsed = parseInitOptions(args);
|
|
5708
|
+
if (parsed.options.yes || parsed.options.server || parsed.options.repoSlug || parsed.options.githubToken || parsed.options.privateStateOnly || parsed.options.repair || parsed.options.githubAuthMethod || parsed.options.remoteCheckout) {
|
|
5709
|
+
if (parsed.rest.length > 0)
|
|
5710
|
+
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5711
|
+
Usage: rig init [--server local|remote] [--remote-url <url>] [--repo owner/repo] [--github-auth gh|token|device|skip] [--github-token <token>] [--github-project off|<project-id>] [--remote-checkout managed-clone|current-ref|uploaded-snapshot|existing-path] [--yes]`, 1);
|
|
5712
|
+
return runControlPlaneInit(context, parsed.options);
|
|
5713
|
+
}
|
|
5714
|
+
if (parsed.rest.length > 0)
|
|
5715
|
+
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5716
|
+
Usage: rig init`, 1);
|
|
5717
|
+
return runInteractiveControlPlaneInit(context, await loadClackPrompts());
|
|
5472
5718
|
}
|
|
5473
5719
|
|
|
5474
5720
|
// packages/cli/src/commands/connect.ts
|
|
5721
|
+
import { cancel as cancel2, isCancel as isCancel2, select as select2 } from "@clack/prompts";
|
|
5475
5722
|
function usageName(options) {
|
|
5476
5723
|
return `rig ${options.group}`;
|
|
5477
5724
|
}
|
|
@@ -5896,8 +6143,8 @@ async function executeInspect(context, args) {
|
|
|
5896
6143
|
switch (command) {
|
|
5897
6144
|
case "logs": {
|
|
5898
6145
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5899
|
-
requireNoExtraArgs(remaining, "
|
|
5900
|
-
const requiredTask = requireTask(task, "
|
|
6146
|
+
requireNoExtraArgs(remaining, "rig inspect logs --task <task-id>");
|
|
6147
|
+
const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
|
|
5901
6148
|
const latestRun = listAuthorityRuns2(context.projectRoot).map((entry) => readAuthorityRun3(context.projectRoot, entry.runId)).filter((run) => Boolean(run)).filter((run) => run.taskId === requiredTask).sort((left, right) => String(right.updatedAt ?? "").localeCompare(String(left.updatedAt ?? "")))[0];
|
|
5902
6149
|
if (!latestRun) {
|
|
5903
6150
|
throw new CliError2(`No runs found for ${requiredTask}.`);
|
|
@@ -5911,8 +6158,8 @@ async function executeInspect(context, args) {
|
|
|
5911
6158
|
}
|
|
5912
6159
|
case "artifacts": {
|
|
5913
6160
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5914
|
-
requireNoExtraArgs(remaining, "
|
|
5915
|
-
const requiredTask = requireTask(task, "
|
|
6161
|
+
requireNoExtraArgs(remaining, "rig inspect artifacts --task <task-id>");
|
|
6162
|
+
const requiredTask = requireTask(task, "rig inspect artifacts --task <task-id>");
|
|
5916
6163
|
const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync11(path));
|
|
5917
6164
|
if (!artifactRoot) {
|
|
5918
6165
|
throw new CliError2(`No artifacts found for ${requiredTask}.`);
|
|
@@ -5926,8 +6173,8 @@ async function executeInspect(context, args) {
|
|
|
5926
6173
|
previewPending = task.rest;
|
|
5927
6174
|
const file = takeOption(previewPending, "--file");
|
|
5928
6175
|
previewPending = file.rest;
|
|
5929
|
-
requireNoExtraArgs(previewPending, "
|
|
5930
|
-
const requiredTask = requireTask(task.value, "
|
|
6176
|
+
requireNoExtraArgs(previewPending, "rig inspect artifact --task <task-id> --file <name>");
|
|
6177
|
+
const requiredTask = requireTask(task.value, "rig inspect artifact --task <task-id> --file <name>");
|
|
5931
6178
|
if (!file.value) {
|
|
5932
6179
|
throw new CliError2("Missing --file for rig inspect artifact.");
|
|
5933
6180
|
}
|
|
@@ -5956,7 +6203,7 @@ async function executeInspect(context, args) {
|
|
|
5956
6203
|
}
|
|
5957
6204
|
case "diff": {
|
|
5958
6205
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5959
|
-
requireNoExtraArgs(remaining, "
|
|
6206
|
+
requireNoExtraArgs(remaining, "rig inspect diff [--task <task-id>]");
|
|
5960
6207
|
if (task) {
|
|
5961
6208
|
const files = changedFilesForTask(context.projectRoot, task, false);
|
|
5962
6209
|
for (const file of files) {
|
|
@@ -5968,7 +6215,7 @@ async function executeInspect(context, args) {
|
|
|
5968
6215
|
return { ok: true, group: "inspect", command, details: { task: task || null } };
|
|
5969
6216
|
}
|
|
5970
6217
|
case "failures": {
|
|
5971
|
-
requireNoExtraArgs(rest, "
|
|
6218
|
+
requireNoExtraArgs(rest, "rig inspect failures");
|
|
5972
6219
|
const failed = resolveHarnessPaths2(context.projectRoot).failedApproachesPath;
|
|
5973
6220
|
if (!existsSync11(failed)) {
|
|
5974
6221
|
console.log("No failures recorded.");
|
|
@@ -5978,7 +6225,7 @@ async function executeInspect(context, args) {
|
|
|
5978
6225
|
return { ok: true, group: "inspect", command };
|
|
5979
6226
|
}
|
|
5980
6227
|
case "graph":
|
|
5981
|
-
requireNoExtraArgs(rest, "
|
|
6228
|
+
requireNoExtraArgs(rest, "rig inspect graph");
|
|
5982
6229
|
{
|
|
5983
6230
|
const monorepoRoot = resolveMonorepoRoot2(context.projectRoot);
|
|
5984
6231
|
const result = runCapture3(["br", "--no-db", "list", "--pretty"], monorepoRoot);
|
|
@@ -5989,7 +6236,7 @@ async function executeInspect(context, args) {
|
|
|
5989
6236
|
}
|
|
5990
6237
|
return { ok: true, group: "inspect", command };
|
|
5991
6238
|
case "audit": {
|
|
5992
|
-
requireNoExtraArgs(rest, "
|
|
6239
|
+
requireNoExtraArgs(rest, "rig inspect audit");
|
|
5993
6240
|
const auditPath = resolve19(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
|
|
5994
6241
|
if (!existsSync11(auditPath)) {
|
|
5995
6242
|
console.log("No audit log found.");
|
|
@@ -6048,7 +6295,7 @@ async function executeInspector(context, args) {
|
|
|
6048
6295
|
pending = secondsResult.rest;
|
|
6049
6296
|
const pollMsResult = takeOption(pending, "--poll-ms");
|
|
6050
6297
|
pending = pollMsResult.rest;
|
|
6051
|
-
requireNoExtraArgs(pending, "
|
|
6298
|
+
requireNoExtraArgs(pending, "rig inspector stream [--once] [--seconds <n>] [--poll-ms <n>]");
|
|
6052
6299
|
const seconds = secondsResult.value ? parseRequiredPositiveInt(secondsResult.value, "--seconds") : null;
|
|
6053
6300
|
const pollMs = pollMsResult.value ? parseRequiredPositiveInt(pollMsResult.value, "--poll-ms") : null;
|
|
6054
6301
|
if (context.outputMode === "json" && !onceResult.value && !seconds) {
|
|
@@ -6142,7 +6389,7 @@ async function executeInspector(context, args) {
|
|
|
6142
6389
|
let pending = rest;
|
|
6143
6390
|
const scanIdResult = takeOption(pending, "--scan-id");
|
|
6144
6391
|
pending = scanIdResult.rest;
|
|
6145
|
-
requireNoExtraArgs(pending, "
|
|
6392
|
+
requireNoExtraArgs(pending, "rig inspector scan-upstream-drift [--scan-id <id>]");
|
|
6146
6393
|
const connection = await ensureLocalRigServerConnection2(context.projectRoot);
|
|
6147
6394
|
const response = await fetch(new URL("/api/inspector/tools/invoke", connection.baseUrl), {
|
|
6148
6395
|
method: "POST",
|
|
@@ -6253,7 +6500,7 @@ async function executeRemote(context, args) {
|
|
|
6253
6500
|
const [subcommand = "list", ...subRest] = rest;
|
|
6254
6501
|
switch (subcommand) {
|
|
6255
6502
|
case "list": {
|
|
6256
|
-
requireNoExtraArgs(subRest, "
|
|
6503
|
+
requireNoExtraArgs(subRest, "rig remote endpoint list");
|
|
6257
6504
|
const endpoints = listManagedRemoteEndpoints(undefined, context.projectRoot);
|
|
6258
6505
|
const redactedEndpoints = endpoints.map((endpoint2) => redactRemoteEndpoint(endpoint2));
|
|
6259
6506
|
if (context.outputMode === "text") {
|
|
@@ -6277,7 +6524,7 @@ async function executeRemote(context, args) {
|
|
|
6277
6524
|
pending2 = port.rest;
|
|
6278
6525
|
const token = takeOption(pending2, "--token");
|
|
6279
6526
|
pending2 = token.rest;
|
|
6280
|
-
requireNoExtraArgs(pending2, "
|
|
6527
|
+
requireNoExtraArgs(pending2, "rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
|
|
6281
6528
|
if (!alias.value || !host.value || !token.value || !port.value) {
|
|
6282
6529
|
throw new CliError2("remote endpoint add requires --alias, --host, --port, and --token.");
|
|
6283
6530
|
}
|
|
@@ -6304,7 +6551,7 @@ async function executeRemote(context, args) {
|
|
|
6304
6551
|
pending2 = port.rest;
|
|
6305
6552
|
const token = takeOption(pending2, "--token");
|
|
6306
6553
|
pending2 = token.rest;
|
|
6307
|
-
requireNoExtraArgs(pending2, "
|
|
6554
|
+
requireNoExtraArgs(pending2, "rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
|
|
6308
6555
|
if (!endpointId.value && !alias.value) {
|
|
6309
6556
|
throw new CliError2("remote endpoint update requires --id <id> or --alias <a>.");
|
|
6310
6557
|
}
|
|
@@ -6327,7 +6574,7 @@ async function executeRemote(context, args) {
|
|
|
6327
6574
|
let pending2 = subRest;
|
|
6328
6575
|
const alias = takeOption(pending2, "--alias");
|
|
6329
6576
|
pending2 = alias.rest;
|
|
6330
|
-
requireNoExtraArgs(pending2, "
|
|
6577
|
+
requireNoExtraArgs(pending2, "rig remote endpoint remove --alias <a>");
|
|
6331
6578
|
if (!alias.value) {
|
|
6332
6579
|
throw new CliError2("remote endpoint remove requires --alias.");
|
|
6333
6580
|
}
|
|
@@ -6344,7 +6591,7 @@ async function executeRemote(context, args) {
|
|
|
6344
6591
|
let pending2 = subRest;
|
|
6345
6592
|
const alias = takeOption(pending2, "--alias");
|
|
6346
6593
|
pending2 = alias.rest;
|
|
6347
|
-
requireNoExtraArgs(pending2, "
|
|
6594
|
+
requireNoExtraArgs(pending2, "rig remote endpoint test --alias <a>");
|
|
6348
6595
|
if (!alias.value) {
|
|
6349
6596
|
throw new CliError2("remote endpoint test requires --alias.");
|
|
6350
6597
|
}
|
|
@@ -6375,7 +6622,7 @@ async function executeRemote(context, args) {
|
|
|
6375
6622
|
}
|
|
6376
6623
|
}
|
|
6377
6624
|
case "migrate": {
|
|
6378
|
-
requireNoExtraArgs(subRest, "
|
|
6625
|
+
requireNoExtraArgs(subRest, "rig remote endpoint migrate");
|
|
6379
6626
|
const result = migrateManagedRemoteEndpoints(context.projectRoot);
|
|
6380
6627
|
if (context.outputMode === "text") {
|
|
6381
6628
|
console.log(`Imported ${result.imported} endpoint(s) from ${result.sourcePath}${result.skipped > 0 ? `, skipped ${result.skipped}` : ""}.`);
|
|
@@ -6383,7 +6630,7 @@ async function executeRemote(context, args) {
|
|
|
6383
6630
|
return { ok: true, group: "remote", command: "endpoint migrate", details: result };
|
|
6384
6631
|
}
|
|
6385
6632
|
case "doctor": {
|
|
6386
|
-
requireNoExtraArgs(subRest, "
|
|
6633
|
+
requireNoExtraArgs(subRest, "rig remote endpoint doctor");
|
|
6387
6634
|
const result = doctorManagedRemoteEndpoints(context.projectRoot);
|
|
6388
6635
|
if (context.outputMode === "text") {
|
|
6389
6636
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -6436,17 +6683,17 @@ async function executeRemote(context, args) {
|
|
|
6436
6683
|
try {
|
|
6437
6684
|
switch (command) {
|
|
6438
6685
|
case "test": {
|
|
6439
|
-
requireNoExtraArgs(pending, "
|
|
6686
|
+
requireNoExtraArgs(pending, "rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6440
6687
|
const response = await withClient((client) => client.ping());
|
|
6441
6688
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6442
6689
|
}
|
|
6443
6690
|
case "status": {
|
|
6444
|
-
requireNoExtraArgs(pending, "
|
|
6691
|
+
requireNoExtraArgs(pending, "rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6445
6692
|
const response = await withClient((client) => client.getState());
|
|
6446
6693
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6447
6694
|
}
|
|
6448
6695
|
case "tasks": {
|
|
6449
|
-
requireNoExtraArgs(pending, "
|
|
6696
|
+
requireNoExtraArgs(pending, "rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6450
6697
|
const response = await withClient((client) => client.getTasks());
|
|
6451
6698
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6452
6699
|
}
|
|
@@ -6456,7 +6703,7 @@ async function executeRemote(context, args) {
|
|
|
6456
6703
|
watchPending = secondsResult.rest;
|
|
6457
6704
|
const eventResult = takeOption(watchPending, "--event");
|
|
6458
6705
|
watchPending = eventResult.rest;
|
|
6459
|
-
requireNoExtraArgs(watchPending, "
|
|
6706
|
+
requireNoExtraArgs(watchPending, "rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6460
6707
|
const seconds = parseOptionalPositiveInt(secondsResult.value, "--seconds");
|
|
6461
6708
|
const eventFilter = eventResult.value || undefined;
|
|
6462
6709
|
if (context.outputMode === "json" && !seconds) {
|
|
@@ -6525,7 +6772,7 @@ async function executeRemote(context, args) {
|
|
|
6525
6772
|
case "stop":
|
|
6526
6773
|
case "continue":
|
|
6527
6774
|
case "refresh": {
|
|
6528
|
-
requireNoExtraArgs(pending, `
|
|
6775
|
+
requireNoExtraArgs(pending, `rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6529
6776
|
const response = await withClient(async (client) => {
|
|
6530
6777
|
switch (command) {
|
|
6531
6778
|
case "pause":
|
|
@@ -6548,7 +6795,7 @@ async function executeRemote(context, args) {
|
|
|
6548
6795
|
let countPending = pending;
|
|
6549
6796
|
const countResult = takeOption(countPending, "--count");
|
|
6550
6797
|
countPending = countResult.rest;
|
|
6551
|
-
requireNoExtraArgs(countPending, `
|
|
6798
|
+
requireNoExtraArgs(countPending, `rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6552
6799
|
const count = parseRequiredPositiveInt(countResult.value, "--count");
|
|
6553
6800
|
const response = await withClient(async (client) => command === "add-iterations" ? await client.addIterations(count) : await client.removeIterations(count));
|
|
6554
6801
|
assertRemoteOperationSuccess(command, response);
|
|
@@ -6559,8 +6806,8 @@ async function executeRemote(context, args) {
|
|
|
6559
6806
|
let taskPending = pending;
|
|
6560
6807
|
const taskResult = takeOption(taskPending, "--task");
|
|
6561
6808
|
taskPending = taskResult.rest;
|
|
6562
|
-
requireNoExtraArgs(taskPending, `
|
|
6563
|
-
const taskId = requireTask(taskResult.value, `
|
|
6809
|
+
requireNoExtraArgs(taskPending, `rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6810
|
+
const taskId = requireTask(taskResult.value, `rig remote ${command} --task <id>`);
|
|
6564
6811
|
const response = await withClient(async (client) => command === "prompt-preview" ? await client.getPromptPreview(taskId) : await client.getIterationOutput(taskId));
|
|
6565
6812
|
assertRemoteOperationSuccess(command, response);
|
|
6566
6813
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
@@ -6573,7 +6820,7 @@ async function executeRemote(context, args) {
|
|
|
6573
6820
|
orchestrationPending = maxIterationsResult.rest;
|
|
6574
6821
|
const directMergeResult = takeFlag(orchestrationPending, "--direct-merge");
|
|
6575
6822
|
orchestrationPending = directMergeResult.rest;
|
|
6576
|
-
requireNoExtraArgs(orchestrationPending, "
|
|
6823
|
+
requireNoExtraArgs(orchestrationPending, "rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
|
|
6577
6824
|
const response = await withClient((client) => client.startOrchestration({
|
|
6578
6825
|
maxWorkers: parseOptionalPositiveInt(maxWorkersResult.value, "--max-workers"),
|
|
6579
6826
|
maxIterations: parseOptionalPositiveInt(maxIterationsResult.value, "--max-iterations"),
|
|
@@ -6594,8 +6841,8 @@ async function executeRemote(context, args) {
|
|
|
6594
6841
|
let orchestrationPending = pending;
|
|
6595
6842
|
const idResult = takeOption(orchestrationPending, "--id");
|
|
6596
6843
|
orchestrationPending = idResult.rest;
|
|
6597
|
-
requireNoExtraArgs(orchestrationPending, `
|
|
6598
|
-
const orchestrationId = requireTask(idResult.value, `
|
|
6844
|
+
requireNoExtraArgs(orchestrationPending, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6845
|
+
const orchestrationId = requireTask(idResult.value, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6599
6846
|
const response = await withClient(async (client) => {
|
|
6600
6847
|
switch (command) {
|
|
6601
6848
|
case "orchestrate-pause":
|
|
@@ -6659,8 +6906,8 @@ var CANONICAL_STAGES = [
|
|
|
6659
6906
|
"Merge",
|
|
6660
6907
|
"Complete"
|
|
6661
6908
|
];
|
|
6662
|
-
function logDetail(
|
|
6663
|
-
return typeof
|
|
6909
|
+
function logDetail(log4) {
|
|
6910
|
+
return typeof log4.detail === "string" ? log4.detail.trim() : "";
|
|
6664
6911
|
}
|
|
6665
6912
|
function parseProviderProtocolLog(title, detail) {
|
|
6666
6913
|
if (title.trim().toLowerCase() !== "agent output")
|
|
@@ -6707,12 +6954,12 @@ function renderOperatorSnapshot(snapshot) {
|
|
|
6707
6954
|
const status = String(run.status ?? "unknown");
|
|
6708
6955
|
const logs = snapshot.logs ?? [];
|
|
6709
6956
|
const latestByStage = new Map;
|
|
6710
|
-
for (const
|
|
6711
|
-
const title = String(
|
|
6712
|
-
const stageName = String(
|
|
6957
|
+
for (const log4 of logs) {
|
|
6958
|
+
const title = String(log4.title ?? "").toLowerCase();
|
|
6959
|
+
const stageName = String(log4.stage ?? "").toLowerCase();
|
|
6713
6960
|
const stage = CANONICAL_STAGES.find((candidate) => candidate.toLowerCase() === title || candidate.toLowerCase() === stageName);
|
|
6714
6961
|
if (stage)
|
|
6715
|
-
latestByStage.set(stage,
|
|
6962
|
+
latestByStage.set(stage, log4);
|
|
6716
6963
|
}
|
|
6717
6964
|
const stageLines = CANONICAL_STAGES.flatMap((stage) => {
|
|
6718
6965
|
const match = latestByStage.get(stage);
|
|
@@ -7516,7 +7763,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
7516
7763
|
}
|
|
7517
7764
|
|
|
7518
7765
|
// packages/cli/src/commands/run.ts
|
|
7519
|
-
function
|
|
7766
|
+
function normalizeRemoteRunDetails2(payload) {
|
|
7520
7767
|
const run = payload.run;
|
|
7521
7768
|
if (!run || typeof run !== "object" || Array.isArray(run))
|
|
7522
7769
|
return null;
|
|
@@ -7528,11 +7775,11 @@ function normalizeRemoteRunDetails(payload) {
|
|
|
7528
7775
|
};
|
|
7529
7776
|
}
|
|
7530
7777
|
var REMOTE_TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged"]);
|
|
7531
|
-
function
|
|
7778
|
+
function isRemoteConnectionSelected2(projectRoot) {
|
|
7532
7779
|
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
7533
7780
|
}
|
|
7534
7781
|
async function listRunsForSelectedConnection(context, options = {}) {
|
|
7535
|
-
if (
|
|
7782
|
+
if (isRemoteConnectionSelected2(context.projectRoot)) {
|
|
7536
7783
|
return { runs: await listRunsViaServer(context, options), source: "server" };
|
|
7537
7784
|
}
|
|
7538
7785
|
return { runs: listAuthorityRuns3(context.projectRoot), source: "local" };
|
|
@@ -7541,9 +7788,6 @@ function runStringField(run, key, fallback = "") {
|
|
|
7541
7788
|
const value = run[key];
|
|
7542
7789
|
return typeof value === "string" && value.trim() ? value : fallback;
|
|
7543
7790
|
}
|
|
7544
|
-
function runDisplayTitle(run) {
|
|
7545
|
-
return runStringField(run, "title", runStringField(run, "taskId", "(untitled)"));
|
|
7546
|
-
}
|
|
7547
7791
|
function buildServerRunStatus(runs) {
|
|
7548
7792
|
const activeRuns = runs.filter((run) => !REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
7549
7793
|
const recentRuns = runs.filter((run) => REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
@@ -7613,10 +7857,10 @@ async function executeRun(context, args) {
|
|
|
7613
7857
|
const runtimeContext = loadRuntimeContextFromEnv2() ?? undefined;
|
|
7614
7858
|
switch (command) {
|
|
7615
7859
|
case "list": {
|
|
7616
|
-
requireNoExtraArgs(rest, "
|
|
7860
|
+
requireNoExtraArgs(rest, "rig run list");
|
|
7617
7861
|
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
7618
7862
|
if (context.outputMode === "text") {
|
|
7619
|
-
|
|
7863
|
+
printFormattedOutput(formatRunList(runs, { source }));
|
|
7620
7864
|
}
|
|
7621
7865
|
return { ok: true, group: "run", command, details: { runs, source } };
|
|
7622
7866
|
}
|
|
@@ -7626,7 +7870,7 @@ async function executeRun(context, args) {
|
|
|
7626
7870
|
pending = run.rest;
|
|
7627
7871
|
const purgeArtifacts = takeFlag(pending, "--purge-artifacts");
|
|
7628
7872
|
pending = purgeArtifacts.rest;
|
|
7629
|
-
requireNoExtraArgs(pending, "
|
|
7873
|
+
requireNoExtraArgs(pending, "rig run delete --run <id> [--purge-artifacts]");
|
|
7630
7874
|
if (!run.value) {
|
|
7631
7875
|
throw new CliError2("run delete requires --run <id>.");
|
|
7632
7876
|
}
|
|
@@ -7656,7 +7900,7 @@ async function executeRun(context, args) {
|
|
|
7656
7900
|
pending = keepRuntimes.rest;
|
|
7657
7901
|
const keepQueue = takeFlag(pending, "--keep-queue");
|
|
7658
7902
|
pending = keepQueue.rest;
|
|
7659
|
-
requireNoExtraArgs(pending, "
|
|
7903
|
+
requireNoExtraArgs(pending, "rig run cleanup --all [--keep-artifacts] [--keep-runtimes] [--keep-queue]");
|
|
7660
7904
|
if (!all.value) {
|
|
7661
7905
|
throw new CliError2("run cleanup currently requires --all.");
|
|
7662
7906
|
}
|
|
@@ -7675,20 +7919,25 @@ async function executeRun(context, args) {
|
|
|
7675
7919
|
}
|
|
7676
7920
|
case "show": {
|
|
7677
7921
|
let pending = rest;
|
|
7922
|
+
const rawResult = takeFlag(pending, "--raw");
|
|
7923
|
+
pending = rawResult.rest;
|
|
7678
7924
|
const run = takeOption(pending, "--run");
|
|
7679
7925
|
pending = run.rest;
|
|
7680
|
-
|
|
7681
|
-
|
|
7682
|
-
|
|
7926
|
+
const positionalRunId = pending.length > 0 && pending[0] && !pending[0].startsWith("-") ? pending[0] : undefined;
|
|
7927
|
+
const extra = positionalRunId ? pending.slice(1) : pending;
|
|
7928
|
+
requireNoExtraArgs(extra, "rig run show <id>|--run <id> [--raw]");
|
|
7929
|
+
const runId = run.value ?? positionalRunId;
|
|
7930
|
+
if (!runId) {
|
|
7931
|
+
throw new CliError2("run show requires a run id.");
|
|
7683
7932
|
}
|
|
7684
|
-
const record = readAuthorityRun4(context.projectRoot,
|
|
7933
|
+
const record = readAuthorityRun4(context.projectRoot, runId) ?? normalizeRemoteRunDetails2(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
7685
7934
|
if (!record) {
|
|
7686
|
-
throw new CliError2(`Run not found: ${
|
|
7935
|
+
throw new CliError2(`Run not found: ${runId}`, 2);
|
|
7687
7936
|
}
|
|
7688
7937
|
if (context.outputMode === "text") {
|
|
7689
|
-
|
|
7938
|
+
printFormattedOutput(rawResult.value ? JSON.stringify(record, null, 2) : formatRunCard(record));
|
|
7690
7939
|
}
|
|
7691
|
-
return { ok: true, group: "run", command, details: record };
|
|
7940
|
+
return { ok: true, group: "run", command, details: { ...record, rawOutput: rawResult.value } };
|
|
7692
7941
|
}
|
|
7693
7942
|
case "timeline": {
|
|
7694
7943
|
let pending = rest;
|
|
@@ -7696,7 +7945,7 @@ async function executeRun(context, args) {
|
|
|
7696
7945
|
pending = run.rest;
|
|
7697
7946
|
const follow = takeFlag(pending, "--follow");
|
|
7698
7947
|
pending = follow.rest;
|
|
7699
|
-
requireNoExtraArgs(pending, "
|
|
7948
|
+
requireNoExtraArgs(pending, "rig run timeline --run <id> [--follow]");
|
|
7700
7949
|
if (!run.value) {
|
|
7701
7950
|
throw new CliError2("run timeline requires --run <id>.");
|
|
7702
7951
|
}
|
|
@@ -7733,7 +7982,7 @@ async function executeRun(context, args) {
|
|
|
7733
7982
|
pending = pollMs.rest;
|
|
7734
7983
|
const positionalRunId = pending.length > 0 ? pending[0] : undefined;
|
|
7735
7984
|
const extra = positionalRunId ? pending.slice(1) : pending;
|
|
7736
|
-
requireNoExtraArgs(extra, "
|
|
7985
|
+
requireNoExtraArgs(extra, "rig run attach <run-id>|--run <run-id> [--message <text>] [--once|--follow] [--poll-ms <ms>]");
|
|
7737
7986
|
const runId = runOption.value ?? positionalRunId;
|
|
7738
7987
|
if (!runId) {
|
|
7739
7988
|
throw new CliError2("run attach requires a run id.", 2);
|
|
@@ -7753,28 +8002,18 @@ async function executeRun(context, args) {
|
|
|
7753
8002
|
return { ok: true, group: "run", command, details: { ...attached, steered: attached.steered || steered } };
|
|
7754
8003
|
}
|
|
7755
8004
|
case "status": {
|
|
7756
|
-
requireNoExtraArgs(rest, "
|
|
8005
|
+
requireNoExtraArgs(rest, "rig run status");
|
|
7757
8006
|
if (context.dryRun) {
|
|
7758
8007
|
if (context.outputMode === "text") {
|
|
7759
8008
|
console.log("[dry-run] rig run status");
|
|
7760
8009
|
}
|
|
7761
8010
|
return { ok: true, group: "run", command };
|
|
7762
8011
|
}
|
|
7763
|
-
const summary =
|
|
8012
|
+
const summary = isRemoteConnectionSelected2(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
7764
8013
|
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7765
8014
|
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7766
8015
|
if (context.outputMode === "text") {
|
|
7767
|
-
|
|
7768
|
-
for (const run of activeRuns) {
|
|
7769
|
-
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
7770
|
-
}
|
|
7771
|
-
if (recentRuns.length > 0) {
|
|
7772
|
-
console.log("");
|
|
7773
|
-
console.log("Recent runs:");
|
|
7774
|
-
for (const run of recentRuns) {
|
|
7775
|
-
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
7776
|
-
}
|
|
7777
|
-
}
|
|
8016
|
+
printFormattedOutput(formatRunStatus({ activeRuns, recentRuns, runs: Array.isArray(summary.runs) ? summary.runs : [...activeRuns, ...recentRuns] }, { source: isRemoteConnectionSelected2(context.projectRoot) ? "server" : "local" }));
|
|
7778
8017
|
}
|
|
7779
8018
|
return { ok: true, group: "run", command, details: summary };
|
|
7780
8019
|
}
|
|
@@ -7798,7 +8037,7 @@ async function executeRun(context, args) {
|
|
|
7798
8037
|
pending = pollResult.rest;
|
|
7799
8038
|
const noServerResult = takeFlag(pending, "--no-server");
|
|
7800
8039
|
pending = noServerResult.rest;
|
|
7801
|
-
requireNoExtraArgs(pending, "
|
|
8040
|
+
requireNoExtraArgs(pending, "rig run start [--epic <id>] [--prompt-epic|--no-epic-prompt] [--ws-port <n>] [--server-host <host>] [--server-port <n>] [--poll-ms <n>] [--no-server]");
|
|
7802
8041
|
if (promptEpicResult.value && noEpicPromptResult.value) {
|
|
7803
8042
|
throw new CliError2("Cannot use --prompt-epic and --no-epic-prompt together.");
|
|
7804
8043
|
}
|
|
@@ -7846,7 +8085,7 @@ async function executeRun(context, args) {
|
|
|
7846
8085
|
};
|
|
7847
8086
|
}
|
|
7848
8087
|
case "resume": {
|
|
7849
|
-
requireNoExtraArgs(rest, "
|
|
8088
|
+
requireNoExtraArgs(rest, "rig run resume");
|
|
7850
8089
|
if (context.dryRun) {
|
|
7851
8090
|
if (context.outputMode === "text") {
|
|
7852
8091
|
console.log("[dry-run] rig run resume");
|
|
@@ -7860,7 +8099,7 @@ async function executeRun(context, args) {
|
|
|
7860
8099
|
return { ok: true, group: "run", command, details: resumed };
|
|
7861
8100
|
}
|
|
7862
8101
|
case "restart": {
|
|
7863
|
-
requireNoExtraArgs(rest, "
|
|
8102
|
+
requireNoExtraArgs(rest, "rig run restart");
|
|
7864
8103
|
if (context.dryRun) {
|
|
7865
8104
|
if (context.outputMode === "text") {
|
|
7866
8105
|
console.log("[dry-run] rig run restart");
|
|
@@ -7877,7 +8116,7 @@ async function executeRun(context, args) {
|
|
|
7877
8116
|
const runOption = takeOption(rest, "--run");
|
|
7878
8117
|
const positionalRunId = runOption.rest.length > 0 ? runOption.rest[0] : undefined;
|
|
7879
8118
|
const extra = positionalRunId ? runOption.rest.slice(1) : runOption.rest;
|
|
7880
|
-
requireNoExtraArgs(extra, "
|
|
8119
|
+
requireNoExtraArgs(extra, "rig run stop [<run-id>|--run <id>]");
|
|
7881
8120
|
const runId = runOption.value ?? positionalRunId;
|
|
7882
8121
|
if (context.dryRun) {
|
|
7883
8122
|
return {
|
|
@@ -8015,73 +8254,425 @@ async function executeServer(context, args, options) {
|
|
|
8015
8254
|
throw new CliError2(`Unknown server command: ${command}`);
|
|
8016
8255
|
}
|
|
8017
8256
|
}
|
|
8018
|
-
|
|
8019
|
-
// packages/cli/src/commands/task.ts
|
|
8020
|
-
import { readFileSync as readFileSync9 } from "fs";
|
|
8021
|
-
import { spawnSync as spawnSync3 } from "child_process";
|
|
8022
|
-
import { resolve as resolve20 } from "path";
|
|
8023
|
-
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
8024
|
-
import {
|
|
8025
|
-
taskArtifactDir,
|
|
8026
|
-
taskArtifacts,
|
|
8027
|
-
taskArtifactWrite,
|
|
8028
|
-
taskDeps,
|
|
8029
|
-
taskInfo,
|
|
8030
|
-
taskLookup as taskLookup2,
|
|
8031
|
-
taskReady,
|
|
8032
|
-
taskRecord,
|
|
8033
|
-
taskReopen,
|
|
8034
|
-
taskScope,
|
|
8035
|
-
taskStatus as taskStatus2,
|
|
8036
|
-
taskValidate,
|
|
8037
|
-
taskVerify
|
|
8038
|
-
} from "@rig/runtime/control-plane/native/task-ops";
|
|
8039
|
-
|
|
8040
|
-
// packages/cli/src/commands/_task-picker.ts
|
|
8041
|
-
import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
|
|
8042
|
-
function taskId2(task) {
|
|
8043
|
-
return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
|
|
8257
|
+
|
|
8258
|
+
// packages/cli/src/commands/task.ts
|
|
8259
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
8260
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
8261
|
+
import { resolve as resolve20 } from "path";
|
|
8262
|
+
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
8263
|
+
import {
|
|
8264
|
+
taskArtifactDir,
|
|
8265
|
+
taskArtifacts,
|
|
8266
|
+
taskArtifactWrite,
|
|
8267
|
+
taskDeps,
|
|
8268
|
+
taskInfo,
|
|
8269
|
+
taskLookup as taskLookup2,
|
|
8270
|
+
taskReady,
|
|
8271
|
+
taskRecord,
|
|
8272
|
+
taskReopen,
|
|
8273
|
+
taskScope,
|
|
8274
|
+
taskStatus as taskStatus2,
|
|
8275
|
+
taskValidate,
|
|
8276
|
+
taskVerify
|
|
8277
|
+
} from "@rig/runtime/control-plane/native/task-ops";
|
|
8278
|
+
|
|
8279
|
+
// packages/cli/src/commands/_task-picker.ts
|
|
8280
|
+
import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
|
|
8281
|
+
function taskId2(task) {
|
|
8282
|
+
return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
|
|
8283
|
+
}
|
|
8284
|
+
async function selectTaskWithTextPicker(tasks, io = {}) {
|
|
8285
|
+
if (tasks.length === 0)
|
|
8286
|
+
return null;
|
|
8287
|
+
if (tasks.length === 1)
|
|
8288
|
+
return tasks[0];
|
|
8289
|
+
const isTty = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
8290
|
+
if (!isTty) {
|
|
8291
|
+
throw new Error("task run requires an interactive terminal to pick a task; pass --task <id>, --next, or --detach with a task id.");
|
|
8292
|
+
}
|
|
8293
|
+
if (io.prompt || io.renderer) {
|
|
8294
|
+
const prompt = io.prompt ?? promptForTaskSelection;
|
|
8295
|
+
const renderer = io.renderer ?? { writeLine: (line) => process.stdout.write(`${line}
|
|
8296
|
+
`) };
|
|
8297
|
+
renderer.writeLine("Select Rig task:");
|
|
8298
|
+
for (const row of renderTaskPickerRows(tasks))
|
|
8299
|
+
renderer.writeLine(` ${row}`);
|
|
8300
|
+
const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
|
|
8301
|
+
if (!answer2)
|
|
8302
|
+
return null;
|
|
8303
|
+
if (/^\d+$/.test(answer2)) {
|
|
8304
|
+
const index2 = Number.parseInt(answer2, 10) - 1;
|
|
8305
|
+
return tasks[index2] ?? null;
|
|
8306
|
+
}
|
|
8307
|
+
return tasks.find((task) => taskId2(task) === answer2) ?? null;
|
|
8308
|
+
}
|
|
8309
|
+
const options = tasks.map((task, index2) => ({
|
|
8310
|
+
value: `${index2}`,
|
|
8311
|
+
label: `${taskId2(task)} \xB7 ${typeof task.title === "string" && task.title.trim() ? task.title.trim() : "Untitled task"}`,
|
|
8312
|
+
hint: typeof task.status === "string" && task.status.trim() ? task.status.trim() : undefined
|
|
8313
|
+
}));
|
|
8314
|
+
const answer = await select3({
|
|
8315
|
+
message: "Select Rig task",
|
|
8316
|
+
options
|
|
8317
|
+
});
|
|
8318
|
+
if (isCancel3(answer)) {
|
|
8319
|
+
cancel3("No task selected.");
|
|
8320
|
+
return null;
|
|
8321
|
+
}
|
|
8322
|
+
const index = Number.parseInt(String(answer), 10);
|
|
8323
|
+
return Number.isFinite(index) ? tasks[index] ?? null : null;
|
|
8324
|
+
}
|
|
8325
|
+
|
|
8326
|
+
// packages/cli/src/commands/_help-catalog.ts
|
|
8327
|
+
import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
|
|
8328
|
+
import pc4 from "picocolors";
|
|
8329
|
+
var TOP_LEVEL_SECTIONS = [
|
|
8330
|
+
{
|
|
8331
|
+
title: "Server",
|
|
8332
|
+
subtitle: "choose the local or remote Rig server that owns this repo",
|
|
8333
|
+
commands: [
|
|
8334
|
+
{ command: "rig server status", description: "Show the selected local/remote server for this repo." },
|
|
8335
|
+
{ command: "rig server use local", description: "Switch this repo back to the local Rig server." },
|
|
8336
|
+
{ command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
|
|
8337
|
+
{ command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
|
|
8338
|
+
{ command: "rig server list", description: "Show saved server aliases, including local." }
|
|
8339
|
+
]
|
|
8340
|
+
},
|
|
8341
|
+
{
|
|
8342
|
+
title: "Tasks",
|
|
8343
|
+
subtitle: "find work, inspect it, and submit Pi-backed workers",
|
|
8344
|
+
commands: [
|
|
8345
|
+
{ command: "rig task list", description: "List tasks from the selected task source/server." },
|
|
8346
|
+
{ command: "rig task next", description: "Show the next matching task as a selected-task card." },
|
|
8347
|
+
{ command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
|
|
8348
|
+
{ command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
|
|
8349
|
+
]
|
|
8350
|
+
},
|
|
8351
|
+
{
|
|
8352
|
+
title: "Runs",
|
|
8353
|
+
subtitle: "observe, attach to, and stop live or recent runs",
|
|
8354
|
+
commands: [
|
|
8355
|
+
{ command: "rig run list", description: "List recent runs from the selected server or local state." },
|
|
8356
|
+
{ command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
|
|
8357
|
+
{ command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
|
|
8358
|
+
{ command: "rig run stop <id>", description: "Request cancellation for a running worker." }
|
|
8359
|
+
]
|
|
8360
|
+
},
|
|
8361
|
+
{
|
|
8362
|
+
title: "Review / inbox",
|
|
8363
|
+
subtitle: "clear blocked runs and configure completion review",
|
|
8364
|
+
commands: [
|
|
8365
|
+
{ command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
|
|
8366
|
+
{ command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
|
|
8367
|
+
{ command: "rig review show|set", description: "Inspect or change the review gate policy." }
|
|
8368
|
+
]
|
|
8369
|
+
},
|
|
8370
|
+
{
|
|
8371
|
+
title: "Health / setup",
|
|
8372
|
+
subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
|
|
8373
|
+
commands: [
|
|
8374
|
+
{ command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
|
|
8375
|
+
{ command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
|
|
8376
|
+
{ command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
|
|
8377
|
+
]
|
|
8378
|
+
}
|
|
8379
|
+
];
|
|
8380
|
+
var PRIMARY_GROUPS = [
|
|
8381
|
+
{
|
|
8382
|
+
name: "server",
|
|
8383
|
+
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
8384
|
+
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
8385
|
+
commands: [
|
|
8386
|
+
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
8387
|
+
{ command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
|
|
8388
|
+
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
8389
|
+
{ command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
|
|
8390
|
+
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
8391
|
+
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
|
|
8392
|
+
],
|
|
8393
|
+
examples: [
|
|
8394
|
+
"rig server status",
|
|
8395
|
+
"rig server add prod https://where.rig-does.work",
|
|
8396
|
+
"rig server use prod",
|
|
8397
|
+
"rig server use local",
|
|
8398
|
+
"rig server start --port 3773"
|
|
8399
|
+
],
|
|
8400
|
+
next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
|
|
8401
|
+
advanced: ["Compatibility alias: `rig connect ...` remains callable."]
|
|
8402
|
+
},
|
|
8403
|
+
{
|
|
8404
|
+
name: "task",
|
|
8405
|
+
summary: "Find work, start Pi-backed runs, and validate task results.",
|
|
8406
|
+
usage: ["rig task <list|next|show|run> [options]"],
|
|
8407
|
+
commands: [
|
|
8408
|
+
{ command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
|
|
8409
|
+
{ command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
|
|
8410
|
+
{ command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
|
|
8411
|
+
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
8412
|
+
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
8413
|
+
{ command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
|
|
8414
|
+
{ command: "report-bug", description: "Create a structured bug report/task." }
|
|
8415
|
+
],
|
|
8416
|
+
examples: [
|
|
8417
|
+
"rig task list --assignee @me --limit 20",
|
|
8418
|
+
"rig task next",
|
|
8419
|
+
"rig task show 123 --raw",
|
|
8420
|
+
"rig task run --next",
|
|
8421
|
+
"rig task run #123 --runtime-adapter pi",
|
|
8422
|
+
"rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
|
|
8423
|
+
],
|
|
8424
|
+
next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
|
|
8425
|
+
},
|
|
8426
|
+
{
|
|
8427
|
+
name: "run",
|
|
8428
|
+
summary: "Observe, attach to, and control Rig runs.",
|
|
8429
|
+
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
8430
|
+
commands: [
|
|
8431
|
+
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
8432
|
+
{ command: "status", description: "Render active and recent run groups.", primary: true },
|
|
8433
|
+
{ command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
|
|
8434
|
+
{ command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; --follow launches native bundled Pi for live Pi runs.", primary: true },
|
|
8435
|
+
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
8436
|
+
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
8437
|
+
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
8438
|
+
],
|
|
8439
|
+
examples: [
|
|
8440
|
+
"rig run list",
|
|
8441
|
+
"rig run status",
|
|
8442
|
+
"rig run show <run-id>",
|
|
8443
|
+
"rig run attach <run-id> --follow",
|
|
8444
|
+
"rig run stop <run-id>"
|
|
8445
|
+
],
|
|
8446
|
+
next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
|
|
8447
|
+
},
|
|
8448
|
+
{
|
|
8449
|
+
name: "inbox",
|
|
8450
|
+
summary: "Review approval and user-input requests that block worker runs.",
|
|
8451
|
+
usage: ["rig inbox <approvals|approve|inputs|respond> [options]"],
|
|
8452
|
+
commands: [
|
|
8453
|
+
{ command: "approvals [--run <id>] [--task <id>]", description: "List pending approvals.", primary: true },
|
|
8454
|
+
{ command: "inputs [--run <id>] [--task <id>]", description: "List pending user-input requests.", primary: true },
|
|
8455
|
+
{ command: "approve --run <id> --request <id> --decision approve|reject", description: "Resolve an approval request." },
|
|
8456
|
+
{ command: "respond --run <id> --request <id> --answer key=value", description: "Answer a user-input request." }
|
|
8457
|
+
],
|
|
8458
|
+
examples: [
|
|
8459
|
+
"rig inbox approvals",
|
|
8460
|
+
"rig inbox inputs --run <run-id>",
|
|
8461
|
+
"rig inbox approve --run <run-id> --request <request-id> --decision approve"
|
|
8462
|
+
],
|
|
8463
|
+
next: ["Rejoin the run after resolving a block: `rig run attach <run-id> --follow`."]
|
|
8464
|
+
},
|
|
8465
|
+
{
|
|
8466
|
+
name: "review",
|
|
8467
|
+
summary: "Inspect or change completion review gate policy.",
|
|
8468
|
+
usage: ["rig review <show|set>"],
|
|
8469
|
+
commands: [
|
|
8470
|
+
{ command: "show", description: "Show current review gate settings.", primary: true },
|
|
8471
|
+
{ command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider.", primary: true }
|
|
8472
|
+
],
|
|
8473
|
+
examples: ["rig review show", "rig review set required --provider greptile"],
|
|
8474
|
+
next: ["Use `rig inbox approvals` for blocked run handoffs."]
|
|
8475
|
+
},
|
|
8476
|
+
{
|
|
8477
|
+
name: "init",
|
|
8478
|
+
summary: "Set up Rig for this repo: server, GitHub auth, checkout strategy, task source, and Pi wiring.",
|
|
8479
|
+
usage: ["rig init [--yes] [--server local|remote] [--repo owner/repo] [--remote-url <url>]"],
|
|
8480
|
+
commands: [
|
|
8481
|
+
{ command: "init", description: "Interactive setup wizard for a new or existing Rig repo.", primary: true },
|
|
8482
|
+
{ command: "init --yes", description: "Non-interactive setup using detected/default settings.", primary: true },
|
|
8483
|
+
{ command: "init --server remote --remote-url <url>", description: "Link this repo to a remote Rig server.", primary: true },
|
|
8484
|
+
{ command: "init --repair", description: "Repair missing private state without replacing project config." }
|
|
8485
|
+
],
|
|
8486
|
+
examples: [
|
|
8487
|
+
"rig init",
|
|
8488
|
+
"rig init --yes --repo humanity-org/humanwork",
|
|
8489
|
+
"rig init --server remote --remote-url https://where.rig-does.work --repo owner/repo"
|
|
8490
|
+
],
|
|
8491
|
+
next: ["After init, run `rig server status`.", "Then use `rig task list` and `rig task run --next` for day-to-day work."]
|
|
8492
|
+
},
|
|
8493
|
+
{
|
|
8494
|
+
name: "doctor",
|
|
8495
|
+
summary: "Diagnostics for project/server/GitHub/Pi state.",
|
|
8496
|
+
usage: ["rig doctor"],
|
|
8497
|
+
commands: [
|
|
8498
|
+
{ command: "doctor", description: "Run setup and runtime diagnostics.", primary: true },
|
|
8499
|
+
{ command: "check", description: "Compatibility spelling for diagnostics." }
|
|
8500
|
+
],
|
|
8501
|
+
examples: ["rig doctor", "rig doctor --json"],
|
|
8502
|
+
next: ["Use `rig server status` and `rig github auth status` to inspect common failure points."]
|
|
8503
|
+
},
|
|
8504
|
+
{
|
|
8505
|
+
name: "github",
|
|
8506
|
+
summary: "GitHub auth helpers for the selected Rig server.",
|
|
8507
|
+
usage: ["rig github auth <status|import-gh|token>"],
|
|
8508
|
+
commands: [
|
|
8509
|
+
{ command: "auth status", description: "Show GitHub auth state.", primary: true },
|
|
8510
|
+
{ command: "auth import-gh", description: "Import the current `gh` token into the selected server." },
|
|
8511
|
+
{ command: "auth token --token <token>", description: "Store a token on the selected server." }
|
|
8512
|
+
],
|
|
8513
|
+
examples: ["rig github auth status", "rig github auth import-gh"],
|
|
8514
|
+
next: ["After auth is valid, use `rig task run --next`."]
|
|
8515
|
+
}
|
|
8516
|
+
];
|
|
8517
|
+
var ADVANCED_GROUPS = [
|
|
8518
|
+
{ name: "connect", summary: "Compatibility alias for `rig server` selection commands.", usage: ["rig connect <status|list|add|use>"], commands: [{ command: "status|list|add|use", description: "Use `rig server ...` for the primary UX." }] },
|
|
8519
|
+
{ name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
|
|
8520
|
+
{ name: "inspect", summary: "Inspect logs, artifacts, graphs, failures.", usage: ["rig inspect <logs|artifacts|failures|graph|audit|diff>"], commands: [{ command: "logs --task <id>", description: "Inspect task logs." }] },
|
|
8521
|
+
{ name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
|
|
8522
|
+
{ name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
|
|
8523
|
+
{ name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
|
|
8524
|
+
{ name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
|
|
8525
|
+
{ name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
|
|
8526
|
+
{ name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
|
|
8527
|
+
{ name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
|
|
8528
|
+
{ name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
|
|
8529
|
+
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
8530
|
+
{ name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
|
|
8531
|
+
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
8532
|
+
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
8533
|
+
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
8534
|
+
];
|
|
8535
|
+
var ADVANCED_COMMANDS = [
|
|
8536
|
+
{ command: "rig server task-run ...", description: "Internal server-owned task execution entry point." },
|
|
8537
|
+
{ command: "rig server notify-test [--event <type>]", description: "Internal event notification smoke command." },
|
|
8538
|
+
{ command: "rig run start|start-serial|start-parallel", description: "Compatibility local run starters; prefer `rig task run ...`." },
|
|
8539
|
+
{ command: "rig setup install-agent-shell", description: "Development helper for materializing the agent shell." },
|
|
8540
|
+
{ command: "rig remote orchestrate-*", description: "Compatibility remote orchestration commands." }
|
|
8541
|
+
];
|
|
8542
|
+
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
8543
|
+
function heading(title) {
|
|
8544
|
+
return pc4.bold(pc4.cyan(title));
|
|
8545
|
+
}
|
|
8546
|
+
function commandLine(command, description) {
|
|
8547
|
+
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
8548
|
+
return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
|
|
8549
|
+
}
|
|
8550
|
+
function renderCommandBlock(commands) {
|
|
8551
|
+
return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8552
|
+
`);
|
|
8553
|
+
}
|
|
8554
|
+
function renderGroup(group) {
|
|
8555
|
+
const lines = [
|
|
8556
|
+
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
8557
|
+
"",
|
|
8558
|
+
pc4.bold("Usage"),
|
|
8559
|
+
...group.usage.map((line) => ` ${line}`),
|
|
8560
|
+
"",
|
|
8561
|
+
pc4.bold("Commands"),
|
|
8562
|
+
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
8563
|
+
];
|
|
8564
|
+
if (group.examples?.length) {
|
|
8565
|
+
lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
|
|
8566
|
+
}
|
|
8567
|
+
if (group.next?.length) {
|
|
8568
|
+
lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
8569
|
+
}
|
|
8570
|
+
if (group.advanced?.length) {
|
|
8571
|
+
lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
8572
|
+
}
|
|
8573
|
+
return lines.join(`
|
|
8574
|
+
`);
|
|
8575
|
+
}
|
|
8576
|
+
function renderTopLevelHelp() {
|
|
8577
|
+
return [
|
|
8578
|
+
`${heading("rig")} ${pc4.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
8579
|
+
pc4.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox/review gates."),
|
|
8580
|
+
"",
|
|
8581
|
+
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
8582
|
+
`${pc4.bold(pc4.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc4.dim(section.subtitle)}`,
|
|
8583
|
+
renderCommandBlock(section.commands),
|
|
8584
|
+
""
|
|
8585
|
+
]),
|
|
8586
|
+
pc4.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
|
|
8587
|
+
"",
|
|
8588
|
+
pc4.bold("Global options"),
|
|
8589
|
+
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8590
|
+
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8591
|
+
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
8592
|
+
].join(`
|
|
8593
|
+
`).trimEnd();
|
|
8044
8594
|
}
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
|
|
8049
|
-
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8595
|
+
function renderAdvancedHelp() {
|
|
8596
|
+
return [
|
|
8597
|
+
`${heading("rig advanced")} \u2014 compatibility, diagnostics, and internal surfaces`,
|
|
8598
|
+
"",
|
|
8599
|
+
pc4.bold("Primary groups"),
|
|
8600
|
+
" server, task, run, inbox, review, init, doctor, github",
|
|
8601
|
+
"",
|
|
8602
|
+
pc4.bold("Advanced commands"),
|
|
8603
|
+
...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
|
|
8604
|
+
"",
|
|
8605
|
+
pc4.bold("Advanced groups"),
|
|
8606
|
+
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
8607
|
+
"",
|
|
8608
|
+
pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, `rig run`, `rig inbox`, and `rig review` for day-to-day work.")
|
|
8609
|
+
].join(`
|
|
8610
|
+
`);
|
|
8611
|
+
}
|
|
8612
|
+
function renderGroupHelp(groupName) {
|
|
8613
|
+
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
8614
|
+
return group ? renderGroup(group) : null;
|
|
8615
|
+
}
|
|
8616
|
+
function shouldUseClackOutput2() {
|
|
8617
|
+
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
8618
|
+
}
|
|
8619
|
+
function printTopLevelHelp() {
|
|
8620
|
+
if (!shouldUseClackOutput2()) {
|
|
8621
|
+
console.log(renderTopLevelHelp());
|
|
8622
|
+
return;
|
|
8053
8623
|
}
|
|
8054
|
-
|
|
8055
|
-
|
|
8056
|
-
|
|
8057
|
-
`) };
|
|
8058
|
-
renderer.writeLine("Select Rig task:");
|
|
8059
|
-
for (const row of renderTaskPickerRows(tasks))
|
|
8060
|
-
renderer.writeLine(` ${row}`);
|
|
8061
|
-
const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
|
|
8062
|
-
if (!answer2)
|
|
8063
|
-
return null;
|
|
8064
|
-
if (/^\d+$/.test(answer2)) {
|
|
8065
|
-
const index2 = Number.parseInt(answer2, 10) - 1;
|
|
8066
|
-
return tasks[index2] ?? null;
|
|
8067
|
-
}
|
|
8068
|
-
return tasks.find((task) => taskId2(task) === answer2) ?? null;
|
|
8624
|
+
intro3("rig");
|
|
8625
|
+
for (const section of TOP_LEVEL_SECTIONS) {
|
|
8626
|
+
note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
|
|
8069
8627
|
}
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8078
|
-
|
|
8079
|
-
|
|
8080
|
-
|
|
8081
|
-
|
|
8628
|
+
log4.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
|
|
8629
|
+
note4([
|
|
8630
|
+
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8631
|
+
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8632
|
+
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
8633
|
+
].join(`
|
|
8634
|
+
`), "Global options");
|
|
8635
|
+
outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
|
|
8636
|
+
}
|
|
8637
|
+
function printAdvancedHelp() {
|
|
8638
|
+
if (!shouldUseClackOutput2()) {
|
|
8639
|
+
console.log(renderAdvancedHelp());
|
|
8640
|
+
return;
|
|
8082
8641
|
}
|
|
8083
|
-
|
|
8084
|
-
|
|
8642
|
+
intro3("rig advanced");
|
|
8643
|
+
note4(ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8644
|
+
`), "Advanced commands");
|
|
8645
|
+
note4(ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)).join(`
|
|
8646
|
+
`), "Advanced groups");
|
|
8647
|
+
outro3("Primary daily flow: rig server \xB7 rig task \xB7 rig run \xB7 rig inbox \xB7 rig review.");
|
|
8648
|
+
}
|
|
8649
|
+
function printGroupHelpDocument(groupName) {
|
|
8650
|
+
const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
|
|
8651
|
+
if (!shouldUseClackOutput2()) {
|
|
8652
|
+
console.log(rendered);
|
|
8653
|
+
return;
|
|
8654
|
+
}
|
|
8655
|
+
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
8656
|
+
if (!group) {
|
|
8657
|
+
printTopLevelHelp();
|
|
8658
|
+
return;
|
|
8659
|
+
}
|
|
8660
|
+
intro3(`rig ${group.name}`);
|
|
8661
|
+
note4(group.summary, "Purpose");
|
|
8662
|
+
note4(group.usage.join(`
|
|
8663
|
+
`), "Usage");
|
|
8664
|
+
note4(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8665
|
+
`), "Commands");
|
|
8666
|
+
if (group.examples?.length)
|
|
8667
|
+
note4(group.examples.map((line) => `$ ${line}`).join(`
|
|
8668
|
+
`), "Examples");
|
|
8669
|
+
if (group.next?.length)
|
|
8670
|
+
note4(group.next.map((line) => `\u203A ${line}`).join(`
|
|
8671
|
+
`), "Next steps");
|
|
8672
|
+
if (group.advanced?.length)
|
|
8673
|
+
log4.info(group.advanced.join(`
|
|
8674
|
+
`));
|
|
8675
|
+
outro3("Run with --json when scripts need structured output.");
|
|
8085
8676
|
}
|
|
8086
8677
|
|
|
8087
8678
|
// packages/cli/src/commands/task.ts
|
|
@@ -8235,27 +8826,30 @@ function summarizeTask(task, options = {}) {
|
|
|
8235
8826
|
...options.raw ? { raw: raw ?? task } : {}
|
|
8236
8827
|
};
|
|
8237
8828
|
}
|
|
8238
|
-
function printTaskSummary(task) {
|
|
8239
|
-
console.log(formatTaskList([task]));
|
|
8240
|
-
}
|
|
8241
8829
|
async function validatorRegistryForTaskCommands(projectRoot) {
|
|
8242
8830
|
return buildPluginHostContext(projectRoot).then((ctx) => ctx?.validatorRegistry ?? undefined).catch(() => {
|
|
8243
8831
|
return;
|
|
8244
8832
|
});
|
|
8245
8833
|
}
|
|
8246
8834
|
async function executeTask(context, args, options) {
|
|
8247
|
-
|
|
8835
|
+
if (args.length === 0) {
|
|
8836
|
+
if (context.outputMode === "text") {
|
|
8837
|
+
printGroupHelpDocument("task");
|
|
8838
|
+
}
|
|
8839
|
+
return { ok: true, group: "task", command: "help" };
|
|
8840
|
+
}
|
|
8841
|
+
const [command = "help", ...rest] = args;
|
|
8248
8842
|
switch (command) {
|
|
8249
8843
|
case "list": {
|
|
8250
8844
|
let pending = rest;
|
|
8251
8845
|
const rawResult = takeFlag(pending, "--raw");
|
|
8252
8846
|
pending = rawResult.rest;
|
|
8253
8847
|
const { filters, rest: remaining } = parseTaskFilters(pending);
|
|
8254
|
-
requireNoExtraArgs(remaining, "
|
|
8848
|
+
requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
8255
8849
|
const tasks = await listWorkspaceTasksViaServer(context, filters);
|
|
8256
8850
|
if (context.outputMode === "text") {
|
|
8257
8851
|
const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
|
|
8258
|
-
|
|
8852
|
+
printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
|
|
8259
8853
|
}
|
|
8260
8854
|
return {
|
|
8261
8855
|
ok: true,
|
|
@@ -8265,10 +8859,13 @@ async function executeTask(context, args, options) {
|
|
|
8265
8859
|
};
|
|
8266
8860
|
}
|
|
8267
8861
|
case "show": {
|
|
8268
|
-
|
|
8862
|
+
let pending = rest;
|
|
8863
|
+
const rawResult = takeFlag(pending, "--raw");
|
|
8864
|
+
pending = rawResult.rest;
|
|
8865
|
+
const taskOption = takeOption(pending, "--task");
|
|
8269
8866
|
const positional = taskOption.rest.length > 0 && taskOption.rest[0] && !taskOption.rest[0].startsWith("-") ? taskOption.rest[0] : undefined;
|
|
8270
8867
|
const remaining = positional ? taskOption.rest.slice(1) : taskOption.rest;
|
|
8271
|
-
requireNoExtraArgs(remaining, "
|
|
8868
|
+
requireNoExtraArgs(remaining, "rig task show <id>|--task <id> [--raw]");
|
|
8272
8869
|
const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
|
|
8273
8870
|
if (!taskId3)
|
|
8274
8871
|
throw new CliError2("task show requires a task id.", 2);
|
|
@@ -8276,19 +8873,20 @@ async function executeTask(context, args, options) {
|
|
|
8276
8873
|
if (!task)
|
|
8277
8874
|
throw new CliError2(`Task not found: ${taskId3}`, 3);
|
|
8278
8875
|
const summary = summarizeTask(task, { raw: true });
|
|
8279
|
-
if (context.outputMode === "text")
|
|
8280
|
-
|
|
8281
|
-
|
|
8876
|
+
if (context.outputMode === "text") {
|
|
8877
|
+
printFormattedOutput(rawResult.value ? JSON.stringify(summary, null, 2) : formatTaskDetails(summary));
|
|
8878
|
+
}
|
|
8879
|
+
return { ok: true, group: "task", command, details: { task: summary, raw: rawResult.value } };
|
|
8282
8880
|
}
|
|
8283
8881
|
case "next": {
|
|
8284
8882
|
const { filters, rest: remaining } = parseTaskFilters(rest);
|
|
8285
|
-
requireNoExtraArgs(remaining, "
|
|
8883
|
+
requireNoExtraArgs(remaining, "rig task next [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
8286
8884
|
const selected = await selectNextWorkspaceTaskViaServer(context, filters);
|
|
8287
8885
|
if (context.outputMode === "text") {
|
|
8288
8886
|
if (selected.task) {
|
|
8289
|
-
|
|
8887
|
+
printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
|
|
8290
8888
|
} else {
|
|
8291
|
-
|
|
8889
|
+
printFormattedOutput("No matching tasks.\n\nNext\n\u203A Try `rig task list` to inspect available work.\n\u203A Check server: `rig server status`");
|
|
8292
8890
|
}
|
|
8293
8891
|
}
|
|
8294
8892
|
return {
|
|
@@ -8304,31 +8902,31 @@ async function executeTask(context, args, options) {
|
|
|
8304
8902
|
}
|
|
8305
8903
|
case "info": {
|
|
8306
8904
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8307
|
-
requireNoExtraArgs(remaining, "
|
|
8905
|
+
requireNoExtraArgs(remaining, "rig task info [--task <task-id>]");
|
|
8308
8906
|
await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, task || undefined));
|
|
8309
8907
|
return { ok: true, group: "task", command, details: { task: task || null } };
|
|
8310
8908
|
}
|
|
8311
8909
|
case "scope": {
|
|
8312
8910
|
const filesFlag = takeFlag(rest, "--files");
|
|
8313
8911
|
const { value: task, rest: remaining } = takeOption(filesFlag.rest, "--task");
|
|
8314
|
-
requireNoExtraArgs(remaining, "
|
|
8912
|
+
requireNoExtraArgs(remaining, "rig task scope [--task <id>] [--files]");
|
|
8315
8913
|
await withMutedConsole(context.outputMode === "json", () => taskScope(context.projectRoot, filesFlag.value, task || undefined));
|
|
8316
8914
|
return { ok: true, group: "task", command, details: { files: filesFlag.value, task: task || null } };
|
|
8317
8915
|
}
|
|
8318
8916
|
case "deps":
|
|
8319
|
-
requireNoExtraArgs(rest, "
|
|
8917
|
+
requireNoExtraArgs(rest, "rig task deps");
|
|
8320
8918
|
await withMutedConsole(context.outputMode === "json", () => taskDeps(context.projectRoot));
|
|
8321
8919
|
return { ok: true, group: "task", command };
|
|
8322
8920
|
case "status":
|
|
8323
|
-
requireNoExtraArgs(rest, "
|
|
8921
|
+
requireNoExtraArgs(rest, "rig task status");
|
|
8324
8922
|
withMutedConsole(context.outputMode === "json", () => taskStatus2(context.projectRoot));
|
|
8325
8923
|
return { ok: true, group: "task", command };
|
|
8326
8924
|
case "artifacts":
|
|
8327
|
-
requireNoExtraArgs(rest, "
|
|
8925
|
+
requireNoExtraArgs(rest, "rig task artifacts");
|
|
8328
8926
|
withMutedConsole(context.outputMode === "json", () => taskArtifacts(context.projectRoot));
|
|
8329
8927
|
return { ok: true, group: "task", command };
|
|
8330
8928
|
case "artifact-dir": {
|
|
8331
|
-
requireNoExtraArgs(rest, "
|
|
8929
|
+
requireNoExtraArgs(rest, "rig task artifact-dir");
|
|
8332
8930
|
const path = taskArtifactDir(context.projectRoot);
|
|
8333
8931
|
if (context.outputMode === "text") {
|
|
8334
8932
|
console.log(path);
|
|
@@ -8337,7 +8935,7 @@ async function executeTask(context, args, options) {
|
|
|
8337
8935
|
}
|
|
8338
8936
|
case "artifact-write": {
|
|
8339
8937
|
if (rest.length < 1) {
|
|
8340
|
-
throw new CliError2(`Usage:
|
|
8938
|
+
throw new CliError2(`Usage: rig task artifact-write <filename> [--file <path>]
|
|
8341
8939
|
` + ` Reads content from stdin (or --file), writes to the active task artifact dir.
|
|
8342
8940
|
` + " Example: echo '...' | rig task artifact-write collection-audit.md");
|
|
8343
8941
|
}
|
|
@@ -8350,7 +8948,7 @@ async function executeTask(context, args, options) {
|
|
|
8350
8948
|
content = await readStdin();
|
|
8351
8949
|
}
|
|
8352
8950
|
if (!artifactFilename) {
|
|
8353
|
-
throw new CliError2("Usage:
|
|
8951
|
+
throw new CliError2("Usage: rig task artifact-write <filename> [--file path]");
|
|
8354
8952
|
}
|
|
8355
8953
|
withMutedConsole(context.outputMode === "json", () => taskArtifactWrite(context.projectRoot, artifactFilename, content));
|
|
8356
8954
|
return { ok: true, group: "task", command, details: { filename: artifactFilename } };
|
|
@@ -8359,11 +8957,11 @@ async function executeTask(context, args, options) {
|
|
|
8359
8957
|
return options.executeTaskReportBug(context, rest);
|
|
8360
8958
|
case "lookup": {
|
|
8361
8959
|
if (rest.length !== 1) {
|
|
8362
|
-
throw new CliError2("Usage:
|
|
8960
|
+
throw new CliError2("Usage: rig task lookup <task-id>");
|
|
8363
8961
|
}
|
|
8364
8962
|
const lookupId = rest[0];
|
|
8365
8963
|
if (!lookupId) {
|
|
8366
|
-
throw new CliError2("Usage:
|
|
8964
|
+
throw new CliError2("Usage: rig task lookup <task-id>");
|
|
8367
8965
|
}
|
|
8368
8966
|
const result = taskLookup2(context.projectRoot, lookupId);
|
|
8369
8967
|
if (context.outputMode === "text") {
|
|
@@ -8373,17 +8971,17 @@ async function executeTask(context, args, options) {
|
|
|
8373
8971
|
}
|
|
8374
8972
|
case "record": {
|
|
8375
8973
|
if (rest.length < 2) {
|
|
8376
|
-
throw new CliError2("Usage:
|
|
8974
|
+
throw new CliError2("Usage: rig task record <decision|failure> <text>");
|
|
8377
8975
|
}
|
|
8378
8976
|
const type = rest[0];
|
|
8379
8977
|
if (type !== "decision" && type !== "failure") {
|
|
8380
|
-
throw new CliError2("Usage:
|
|
8978
|
+
throw new CliError2("Usage: rig task record <decision|failure> <text>");
|
|
8381
8979
|
}
|
|
8382
8980
|
withMutedConsole(context.outputMode === "json", () => taskRecord(context.projectRoot, type, rest.slice(1).join(" ")));
|
|
8383
8981
|
return { ok: true, group: "task", command, details: { type: rest[0] } };
|
|
8384
8982
|
}
|
|
8385
8983
|
case "ready":
|
|
8386
|
-
requireNoExtraArgs(rest, "
|
|
8984
|
+
requireNoExtraArgs(rest, "rig task ready");
|
|
8387
8985
|
await withMutedConsole(context.outputMode === "json", () => taskReady(context.projectRoot));
|
|
8388
8986
|
return { ok: true, group: "task", command };
|
|
8389
8987
|
case "run": {
|
|
@@ -8420,7 +9018,7 @@ async function executeTask(context, args, options) {
|
|
|
8420
9018
|
if (positionalTaskId) {
|
|
8421
9019
|
pending = pending.slice(1);
|
|
8422
9020
|
}
|
|
8423
|
-
requireNoExtraArgs(pending, "
|
|
9021
|
+
requireNoExtraArgs(pending, "rig task run [#<issue>|<task-id>] [--next] [--task <id>] [--detach] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>] [--title <text>] [--runtime-adapter claude-code|codex|pi] [--model <model>] [--runtime-mode <mode>] [--interaction-mode <mode>] [--initial-prompt <text>] [--pr auto|ask|off] [--no-pr] [--dirty-baseline head|dirty-snapshot] [--skip-project-sync]");
|
|
8424
9022
|
if (nextResult.value && (taskResult.value || positionalTaskId)) {
|
|
8425
9023
|
throw new CliError2("task run cannot combine --next with an explicit task id.", 2);
|
|
8426
9024
|
}
|
|
@@ -8474,10 +9072,24 @@ async function executeTask(context, args, options) {
|
|
|
8474
9072
|
});
|
|
8475
9073
|
let attachDetails = null;
|
|
8476
9074
|
if (!detachResult.value && context.outputMode === "text") {
|
|
8477
|
-
|
|
9075
|
+
printFormattedOutput(formatSubmittedRun({
|
|
9076
|
+
runId: submitted.runId,
|
|
9077
|
+
task: selectedTask ? summarizeTask(selectedTask) : null,
|
|
9078
|
+
runtimeAdapter,
|
|
9079
|
+
runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
|
|
9080
|
+
interactionMode: interactionModeResult.value || "default",
|
|
9081
|
+
detached: false
|
|
9082
|
+
}));
|
|
8478
9083
|
attachDetails = await attachRunOperatorView(context, { runId: submitted.runId, follow: true });
|
|
8479
9084
|
} else if (context.outputMode === "text") {
|
|
8480
|
-
|
|
9085
|
+
printFormattedOutput(formatSubmittedRun({
|
|
9086
|
+
runId: submitted.runId,
|
|
9087
|
+
task: selectedTask ? summarizeTask(selectedTask) : null,
|
|
9088
|
+
runtimeAdapter,
|
|
9089
|
+
runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
|
|
9090
|
+
interactionMode: interactionModeResult.value || "default",
|
|
9091
|
+
detached: true
|
|
9092
|
+
}));
|
|
8481
9093
|
}
|
|
8482
9094
|
return {
|
|
8483
9095
|
ok: true,
|
|
@@ -8501,7 +9113,7 @@ async function executeTask(context, args, options) {
|
|
|
8501
9113
|
}
|
|
8502
9114
|
case "validate": {
|
|
8503
9115
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8504
|
-
requireNoExtraArgs(remaining, "
|
|
9116
|
+
requireNoExtraArgs(remaining, "rig task validate [--task <task-id>]");
|
|
8505
9117
|
if (context.dryRun) {
|
|
8506
9118
|
await context.runCommand(["rig", "task", "validate", ...task ? ["--task", task] : []]);
|
|
8507
9119
|
return { ok: true, group: "task", command, details: { task: task || "active" } };
|
|
@@ -8514,7 +9126,7 @@ async function executeTask(context, args, options) {
|
|
|
8514
9126
|
}
|
|
8515
9127
|
case "verify": {
|
|
8516
9128
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8517
|
-
requireNoExtraArgs(remaining, "
|
|
9129
|
+
requireNoExtraArgs(remaining, "rig task verify [--task <task-id>]");
|
|
8518
9130
|
if (context.dryRun) {
|
|
8519
9131
|
await context.runCommand(["rig", "task", "verify", ...task ? ["--task", task] : []]);
|
|
8520
9132
|
return { ok: true, group: "task", command, details: { task: task || "active" } };
|
|
@@ -8527,15 +9139,15 @@ async function executeTask(context, args, options) {
|
|
|
8527
9139
|
}
|
|
8528
9140
|
case "reset": {
|
|
8529
9141
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8530
|
-
requireNoExtraArgs(remaining, "
|
|
8531
|
-
const requiredTask = requireTask(task, "
|
|
9142
|
+
requireNoExtraArgs(remaining, "rig task reset --task <task-id>");
|
|
9143
|
+
const requiredTask = requireTask(task, "rig task reset --task <task-id>");
|
|
8532
9144
|
await context.runCommand(["br", "--no-db", "update", requiredTask, "--status", "open"]);
|
|
8533
9145
|
return { ok: true, group: "task", command, details: { task: requiredTask } };
|
|
8534
9146
|
}
|
|
8535
9147
|
case "details": {
|
|
8536
9148
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8537
|
-
requireNoExtraArgs(remaining, "
|
|
8538
|
-
const requiredTask = requireTask(task, "
|
|
9149
|
+
requireNoExtraArgs(remaining, "rig task details --task <task-id>");
|
|
9150
|
+
const requiredTask = requireTask(task, "rig task details --task <task-id>");
|
|
8539
9151
|
await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, requiredTask));
|
|
8540
9152
|
return { ok: true, group: "task", command, details: { task: requiredTask } };
|
|
8541
9153
|
}
|
|
@@ -8543,9 +9155,9 @@ async function executeTask(context, args, options) {
|
|
|
8543
9155
|
const { value: task, rest: rest1 } = takeOption(rest, "--task");
|
|
8544
9156
|
const allFlag = takeFlag(rest1, "--all");
|
|
8545
9157
|
const { rest: remaining } = takeOption(allFlag.rest, "--reason");
|
|
8546
|
-
requireNoExtraArgs(remaining, "
|
|
9158
|
+
requireNoExtraArgs(remaining, "rig task reopen [--task <id> | --all] [--reason <text>]");
|
|
8547
9159
|
if (!allFlag.value && !task) {
|
|
8548
|
-
throw new CliError2("Usage:
|
|
9160
|
+
throw new CliError2("Usage: rig task reopen [--task <id> | --all] [--reason <text>]");
|
|
8549
9161
|
}
|
|
8550
9162
|
const summary = withMutedConsole(context.outputMode === "json", () => taskReopen(context.projectRoot, {
|
|
8551
9163
|
all: allFlag.value,
|
|
@@ -10580,15 +11192,15 @@ async function executeTest(context, args) {
|
|
|
10580
11192
|
const [command = "unit", ...rest] = args;
|
|
10581
11193
|
switch (command) {
|
|
10582
11194
|
case "unit":
|
|
10583
|
-
requireNoExtraArgs(rest, "
|
|
11195
|
+
requireNoExtraArgs(rest, "rig test unit");
|
|
10584
11196
|
await context.runCommand(["bun", "test", "tests/harness/", "--ignore", "tests/harness/e2e/**"]);
|
|
10585
11197
|
return { ok: true, group: "test", command };
|
|
10586
11198
|
case "e2e":
|
|
10587
|
-
requireNoExtraArgs(rest, "
|
|
11199
|
+
requireNoExtraArgs(rest, "rig test e2e");
|
|
10588
11200
|
await context.runCommand(["bun", "test", "tests/harness/e2e/"]);
|
|
10589
11201
|
return { ok: true, group: "test", command };
|
|
10590
11202
|
case "all":
|
|
10591
|
-
requireNoExtraArgs(rest, "
|
|
11203
|
+
requireNoExtraArgs(rest, "rig test all");
|
|
10592
11204
|
await context.runCommand(["bun", "test", "tests/harness/"]);
|
|
10593
11205
|
return { ok: true, group: "test", command };
|
|
10594
11206
|
default:
|
|
@@ -10608,7 +11220,7 @@ async function executeSetup(context, args) {
|
|
|
10608
11220
|
const [command = "check", ...rest] = args;
|
|
10609
11221
|
switch (command) {
|
|
10610
11222
|
case "bootstrap":
|
|
10611
|
-
requireNoExtraArgs(rest, "
|
|
11223
|
+
requireNoExtraArgs(rest, "rig setup bootstrap");
|
|
10612
11224
|
{
|
|
10613
11225
|
const hostBash = Bun.which("bash") || "/bin/bash";
|
|
10614
11226
|
const env = { ...process.env };
|
|
@@ -10631,21 +11243,21 @@ async function executeSetup(context, args) {
|
|
|
10631
11243
|
}
|
|
10632
11244
|
return { ok: true, group: "setup", command };
|
|
10633
11245
|
case "check":
|
|
10634
|
-
requireNoExtraArgs(rest, `
|
|
11246
|
+
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
10635
11247
|
{
|
|
10636
11248
|
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
10637
11249
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
10638
11250
|
}
|
|
10639
11251
|
case "setup":
|
|
10640
|
-
requireNoExtraArgs(rest, "
|
|
11252
|
+
requireNoExtraArgs(rest, "rig setup setup");
|
|
10641
11253
|
withMutedConsole(context.outputMode === "json", () => runSetupInit(context.projectRoot));
|
|
10642
11254
|
return { ok: true, group: "setup", command };
|
|
10643
11255
|
case "preflight":
|
|
10644
|
-
requireNoExtraArgs(rest, "
|
|
11256
|
+
requireNoExtraArgs(rest, "rig setup preflight");
|
|
10645
11257
|
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
10646
11258
|
return { ok: true, group: "setup", command };
|
|
10647
11259
|
case "install-agent-shell":
|
|
10648
|
-
requireNoExtraArgs(rest, "
|
|
11260
|
+
requireNoExtraArgs(rest, "rig setup install-agent-shell");
|
|
10649
11261
|
if (context.outputMode === "text") {
|
|
10650
11262
|
console.log("install-agent-shell is deprecated. Runtime shells now use compiled rig-agent directly.");
|
|
10651
11263
|
}
|
|
@@ -10710,7 +11322,7 @@ async function executeWorkspace(context, args) {
|
|
|
10710
11322
|
const [command = "summary", ...rest] = args;
|
|
10711
11323
|
switch (command) {
|
|
10712
11324
|
case "summary": {
|
|
10713
|
-
requireNoExtraArgs(rest, "
|
|
11325
|
+
requireNoExtraArgs(rest, "rig workspace summary");
|
|
10714
11326
|
const summary = await readWorkspaceSummary(context.projectRoot);
|
|
10715
11327
|
if (context.outputMode === "text") {
|
|
10716
11328
|
console.log("Workspace Summary");
|
|
@@ -10735,7 +11347,7 @@ Warnings:`);
|
|
|
10735
11347
|
return { ok: true, group: "workspace", command, details: summary };
|
|
10736
11348
|
}
|
|
10737
11349
|
case "topology": {
|
|
10738
|
-
requireNoExtraArgs(rest, "
|
|
11350
|
+
requireNoExtraArgs(rest, "rig workspace topology");
|
|
10739
11351
|
const topology = readWorkspaceTopology(context.projectRoot);
|
|
10740
11352
|
if (context.outputMode === "text") {
|
|
10741
11353
|
console.log(`Topology: ${topology.status}`);
|
|
@@ -10748,7 +11360,7 @@ Warnings:`);
|
|
|
10748
11360
|
return { ok: true, group: "workspace", command, details: topology };
|
|
10749
11361
|
}
|
|
10750
11362
|
case "remote-hosts": {
|
|
10751
|
-
requireNoExtraArgs(rest, "
|
|
11363
|
+
requireNoExtraArgs(rest, "rig workspace remote-hosts");
|
|
10752
11364
|
const fleet = readWorkspaceRemoteFleet(context.projectRoot);
|
|
10753
11365
|
if (context.outputMode === "text") {
|
|
10754
11366
|
console.log(`Remote Hosts: ${fleet.status}`);
|
|
@@ -10763,7 +11375,7 @@ Warnings:`);
|
|
|
10763
11375
|
let pending = serviceRest;
|
|
10764
11376
|
const services = takeOption(pending, "--service");
|
|
10765
11377
|
pending = services.rest;
|
|
10766
|
-
requireNoExtraArgs(pending, "
|
|
11378
|
+
requireNoExtraArgs(pending, "rig workspace service-fabric <status|up|verify|down> [--service <name>]");
|
|
10767
11379
|
if (action !== "status" && action !== "up" && action !== "verify" && action !== "down") {
|
|
10768
11380
|
throw new CliError2(`Unknown workspace service-fabric action: ${action}`);
|
|
10769
11381
|
}
|
|
@@ -10784,171 +11396,6 @@ Warnings:`);
|
|
|
10784
11396
|
}
|
|
10785
11397
|
}
|
|
10786
11398
|
|
|
10787
|
-
// packages/cli/src/commands/_help-catalog.ts
|
|
10788
|
-
import pc4 from "picocolors";
|
|
10789
|
-
var PRIMARY_GROUPS = [
|
|
10790
|
-
{
|
|
10791
|
-
name: "server",
|
|
10792
|
-
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
10793
|
-
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
10794
|
-
commands: [
|
|
10795
|
-
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
10796
|
-
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
10797
|
-
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
10798
|
-
{ command: "use [alias|local]", description: "Select a server; prompts in an interactive TTY.", primary: true },
|
|
10799
|
-
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process.", primary: true }
|
|
10800
|
-
],
|
|
10801
|
-
examples: [
|
|
10802
|
-
"rig server status",
|
|
10803
|
-
"rig server add prod https://where.rig-does.work",
|
|
10804
|
-
"rig server use prod",
|
|
10805
|
-
"rig server use local",
|
|
10806
|
-
"rig server start --port 3773"
|
|
10807
|
-
],
|
|
10808
|
-
next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
|
|
10809
|
-
advanced: ["Compatibility alias: `rig connect ...` remains callable."]
|
|
10810
|
-
},
|
|
10811
|
-
{
|
|
10812
|
-
name: "task",
|
|
10813
|
-
summary: "Find work, start Pi-backed runs, and validate task results.",
|
|
10814
|
-
usage: ["rig task <list|next|show|run> [options]"],
|
|
10815
|
-
commands: [
|
|
10816
|
-
{ command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
|
|
10817
|
-
{ command: "next [filters]", description: "Pick the next matching task.", primary: true },
|
|
10818
|
-
{ command: "show <id>|--task <id>", description: "Show task details.", primary: true },
|
|
10819
|
-
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
10820
|
-
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
10821
|
-
{ command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
|
|
10822
|
-
{ command: "report-bug", description: "Create a structured bug report/task." }
|
|
10823
|
-
],
|
|
10824
|
-
examples: [
|
|
10825
|
-
"rig task list --assignee @me --limit 20",
|
|
10826
|
-
"rig task run --next",
|
|
10827
|
-
"rig task run #123 --runtime-adapter pi",
|
|
10828
|
-
"rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
|
|
10829
|
-
],
|
|
10830
|
-
next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
|
|
10831
|
-
},
|
|
10832
|
-
{
|
|
10833
|
-
name: "run",
|
|
10834
|
-
summary: "Observe, attach to, and control Rig runs.",
|
|
10835
|
-
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
10836
|
-
commands: [
|
|
10837
|
-
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
10838
|
-
{ command: "status", description: "Summarize active and recent runs.", primary: true },
|
|
10839
|
-
{ command: "show --run <id>", description: "Show one run record.", primary: true },
|
|
10840
|
-
{ command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; `--follow` launches native bundled Pi for live Pi runs.", primary: true },
|
|
10841
|
-
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
10842
|
-
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
10843
|
-
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
10844
|
-
],
|
|
10845
|
-
examples: [
|
|
10846
|
-
"rig run list",
|
|
10847
|
-
"rig run attach 01234567-89ab-cdef-0123-456789abcdef --follow",
|
|
10848
|
-
"rig run show --run <run-id>",
|
|
10849
|
-
"rig run stop <run-id>"
|
|
10850
|
-
],
|
|
10851
|
-
next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
|
|
10852
|
-
}
|
|
10853
|
-
];
|
|
10854
|
-
var ADVANCED_GROUPS = [
|
|
10855
|
-
{ name: "init", summary: "Initialize or repair Rig project state.", usage: ["rig init [options]"], commands: [{ command: "init", description: "Configure project/server/GitHub integration." }] },
|
|
10856
|
-
{ name: "connect", summary: "Compatibility alias for `rig server` selection commands.", usage: ["rig connect <status|list|add|use>"], commands: [{ command: "status|list|add|use", description: "Use `rig server ...` for the primary UX." }] },
|
|
10857
|
-
{ name: "github", summary: "GitHub auth helpers.", usage: ["rig github auth <status|import-gh|token>"], commands: [{ command: "auth status", description: "Show GitHub auth state." }] },
|
|
10858
|
-
{ name: "doctor", summary: "Diagnostics for project/server/GitHub/Pi state.", usage: ["rig doctor [check|run|shared|...]"], commands: [{ command: "check", description: "Run diagnostics." }] },
|
|
10859
|
-
{ name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
|
|
10860
|
-
{ name: "inspect", summary: "Inspect logs, artifacts, graphs, failures.", usage: ["rig inspect <logs|artifacts|failures|graph|audit|diff>"], commands: [{ command: "logs --task <id>", description: "Inspect task logs." }] },
|
|
10861
|
-
{ name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
|
|
10862
|
-
{ name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
|
|
10863
|
-
{ name: "review", summary: "Review policy configuration.", usage: ["rig review <show|set>"], commands: [{ command: "show", description: "Show review settings." }] },
|
|
10864
|
-
{ name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
|
|
10865
|
-
{ name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
|
|
10866
|
-
{ name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
|
|
10867
|
-
{ name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
|
|
10868
|
-
{ name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
|
|
10869
|
-
{ name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
|
|
10870
|
-
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
10871
|
-
{ name: "remote", summary: "Legacy remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
|
|
10872
|
-
{ name: "inbox", summary: "Approval/input inbox for blocked runs.", usage: ["rig inbox <approvals|approve|inputs|respond>"], commands: [{ command: "approvals", description: "List pending approvals." }] },
|
|
10873
|
-
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
10874
|
-
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
10875
|
-
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
10876
|
-
];
|
|
10877
|
-
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
10878
|
-
function heading(title) {
|
|
10879
|
-
return pc4.bold(pc4.cyan(title));
|
|
10880
|
-
}
|
|
10881
|
-
function commandLine(command, description) {
|
|
10882
|
-
const commandColumn = command.length >= 34 ? `${command} ` : command.padEnd(34);
|
|
10883
|
-
return ` ${pc4.bold(commandColumn)} ${description}`;
|
|
10884
|
-
}
|
|
10885
|
-
function renderGroup(group) {
|
|
10886
|
-
const lines = [
|
|
10887
|
-
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
10888
|
-
"",
|
|
10889
|
-
pc4.bold("Usage"),
|
|
10890
|
-
...group.usage.map((line) => ` ${line}`),
|
|
10891
|
-
"",
|
|
10892
|
-
pc4.bold("Commands"),
|
|
10893
|
-
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
10894
|
-
];
|
|
10895
|
-
if (group.examples?.length) {
|
|
10896
|
-
lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
|
|
10897
|
-
}
|
|
10898
|
-
if (group.next?.length) {
|
|
10899
|
-
lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
10900
|
-
}
|
|
10901
|
-
if (group.advanced?.length) {
|
|
10902
|
-
lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
10903
|
-
}
|
|
10904
|
-
return lines.join(`
|
|
10905
|
-
`);
|
|
10906
|
-
}
|
|
10907
|
-
function renderTopLevelHelp() {
|
|
10908
|
-
return [
|
|
10909
|
-
`${heading("rig")} \u2014 server-owned task/run control plane`,
|
|
10910
|
-
"",
|
|
10911
|
-
pc4.bold("Common workflows"),
|
|
10912
|
-
" rig server status Show selected local/remote server",
|
|
10913
|
-
" rig task list List available work",
|
|
10914
|
-
" rig task run --next Start next task and attach with native Pi",
|
|
10915
|
-
" rig run list List recent runs",
|
|
10916
|
-
" rig run attach <run-id> --follow Rejoin a live run",
|
|
10917
|
-
"",
|
|
10918
|
-
pc4.bold("Primary groups"),
|
|
10919
|
-
...PRIMARY_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
10920
|
-
"",
|
|
10921
|
-
pc4.bold("Help"),
|
|
10922
|
-
" rig <group> --help Rich help for server, task, run, and other groups",
|
|
10923
|
-
" rig help --advanced Legacy/dev/compat command surface",
|
|
10924
|
-
" rig --version Print version",
|
|
10925
|
-
"",
|
|
10926
|
-
pc4.bold("Global options"),
|
|
10927
|
-
" --project <path> Use a project root instead of auto-discovery",
|
|
10928
|
-
" --json Output structured JSON",
|
|
10929
|
-
" --dry-run Print command execution plan only"
|
|
10930
|
-
].join(`
|
|
10931
|
-
`);
|
|
10932
|
-
}
|
|
10933
|
-
function renderAdvancedHelp() {
|
|
10934
|
-
return [
|
|
10935
|
-
`${heading("rig advanced")} \u2014 legacy, dev, and compatibility groups`,
|
|
10936
|
-
"",
|
|
10937
|
-
pc4.bold("Primary groups are still"),
|
|
10938
|
-
" server, task, run",
|
|
10939
|
-
"",
|
|
10940
|
-
pc4.bold("Advanced groups"),
|
|
10941
|
-
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
10942
|
-
"",
|
|
10943
|
-
pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, and `rig run` for day-to-day work.")
|
|
10944
|
-
].join(`
|
|
10945
|
-
`);
|
|
10946
|
-
}
|
|
10947
|
-
function renderGroupHelp(groupName) {
|
|
10948
|
-
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
10949
|
-
return group ? renderGroup(group) : null;
|
|
10950
|
-
}
|
|
10951
|
-
|
|
10952
11399
|
// packages/cli/src/commands.ts
|
|
10953
11400
|
import { ensureProjectMainFreshBeforeRun as ensureProjectMainFreshBeforeRun2 } from "@rig/runtime/control-plane/project-main-pre-run-sync";
|
|
10954
11401
|
var TOP_LEVEL_ALIASES = {
|
|
@@ -10960,7 +11407,7 @@ var TOP_LEVEL_ALIASES = {
|
|
|
10960
11407
|
status: ["run", "status"],
|
|
10961
11408
|
start: ["task", "run", "--next"],
|
|
10962
11409
|
"start-parallel": ["run", "start-parallel"],
|
|
10963
|
-
"start-serial": ["
|
|
11410
|
+
"start-serial": ["run", "start-serial"],
|
|
10964
11411
|
resume: ["run", "resume"],
|
|
10965
11412
|
stop: ["run", "stop"],
|
|
10966
11413
|
ready: ["task", "ready"],
|
|
@@ -11016,7 +11463,7 @@ var GROUPS = new Set([
|
|
|
11016
11463
|
"test"
|
|
11017
11464
|
]);
|
|
11018
11465
|
function printGroupHelp(group) {
|
|
11019
|
-
|
|
11466
|
+
printGroupHelpDocument(group);
|
|
11020
11467
|
}
|
|
11021
11468
|
function isHelpArg(arg) {
|
|
11022
11469
|
return arg === "--help" || arg === "-h" || arg === "help";
|
|
@@ -11026,7 +11473,7 @@ function helpText() {
|
|
|
11026
11473
|
}
|
|
11027
11474
|
async function execute(context, args) {
|
|
11028
11475
|
if (args.length === 0) {
|
|
11029
|
-
|
|
11476
|
+
printTopLevelHelp();
|
|
11030
11477
|
return { ok: true, group: "help", command: "show" };
|
|
11031
11478
|
}
|
|
11032
11479
|
const [first, ...rest] = args;
|
|
@@ -11037,14 +11484,14 @@ ${helpText()}`);
|
|
|
11037
11484
|
}
|
|
11038
11485
|
if (first === "help" || first === "--help" || first === "-h") {
|
|
11039
11486
|
if (rest[0] === "--advanced") {
|
|
11040
|
-
|
|
11487
|
+
printAdvancedHelp();
|
|
11041
11488
|
return { ok: true, group: "help", command: "advanced" };
|
|
11042
11489
|
}
|
|
11043
11490
|
if (rest[0]) {
|
|
11044
|
-
|
|
11491
|
+
printGroupHelp(rest[0]);
|
|
11045
11492
|
return { ok: true, group: "help", command: rest[0] };
|
|
11046
11493
|
}
|
|
11047
|
-
|
|
11494
|
+
printTopLevelHelp();
|
|
11048
11495
|
return { ok: true, group: "help", command: "show" };
|
|
11049
11496
|
}
|
|
11050
11497
|
if (first === "--version" || first === "-V" || first === "version") {
|