@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/src/commands.js
CHANGED
|
@@ -288,15 +288,15 @@ function buildBugReportMarkdown(input, browser, screenshots, assets) {
|
|
|
288
288
|
...input.issueId ? [
|
|
289
289
|
`- Canonical task assets live under \`artifacts/${input.issueId}/bug-report/\`.`,
|
|
290
290
|
`- Start with \`artifacts/${input.issueId}/bug-report/task.md\` and the files in \`artifacts/${input.issueId}/bug-report/assets/\`.`,
|
|
291
|
-
browserRequired ? `- Run \`
|
|
291
|
+
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.`
|
|
292
292
|
] : [
|
|
293
|
-
"- Draft-only report: convert this into a
|
|
293
|
+
"- Draft-only report: convert this into a Rig task before assigning it to an agent run."
|
|
294
294
|
],
|
|
295
295
|
"",
|
|
296
296
|
"## Validation",
|
|
297
297
|
"",
|
|
298
298
|
"```bash",
|
|
299
|
-
...input.issueId ? [`
|
|
299
|
+
...input.issueId ? [`rig task validate --task ${input.issueId}`] : [],
|
|
300
300
|
...browserRequired ? [
|
|
301
301
|
"bun run app:check:browser:hp-next",
|
|
302
302
|
"bun run app:e2e:browser:hp-next"
|
|
@@ -443,7 +443,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
443
443
|
pending = outputRootResult.rest;
|
|
444
444
|
const slugResult = takeOption(pending, "--slug");
|
|
445
445
|
pending = slugResult.rest;
|
|
446
|
-
requireNoExtraArgs(pending, "
|
|
446
|
+
requireNoExtraArgs(pending, "rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
|
|
447
447
|
let draft = {
|
|
448
448
|
outputRoot: outputRootResult.value || "",
|
|
449
449
|
title: titleResult.value,
|
|
@@ -548,7 +548,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
548
548
|
console.log(`Evidence assets: ${result.assetDir}`);
|
|
549
549
|
if (taskConfigPath) {
|
|
550
550
|
console.log(`Task config: ${taskConfigPath}`);
|
|
551
|
-
console.log(`Run:
|
|
551
|
+
console.log(`Run: rig task info --task ${issueId}`);
|
|
552
552
|
}
|
|
553
553
|
}
|
|
554
554
|
return {
|
|
@@ -1371,7 +1371,7 @@ async function executeBrowser(context, args) {
|
|
|
1371
1371
|
return { ok: true, group: "browser", command: "help" };
|
|
1372
1372
|
}
|
|
1373
1373
|
if (command === "explain") {
|
|
1374
|
-
requireNoExtraArgs(rest, "
|
|
1374
|
+
requireNoExtraArgs(rest, "rig browser explain");
|
|
1375
1375
|
console.log(browserAgentUsageText());
|
|
1376
1376
|
return { ok: true, group: "browser", command: "explain" };
|
|
1377
1377
|
}
|
|
@@ -1397,7 +1397,7 @@ ${browserHelpText()}`);
|
|
|
1397
1397
|
|
|
1398
1398
|
${browserHelpText()}`);
|
|
1399
1399
|
}
|
|
1400
|
-
requireNoExtraArgs(appRest, `
|
|
1400
|
+
requireNoExtraArgs(appRest, `rig browser ${command} ${subcommand}`);
|
|
1401
1401
|
await context.runCommand(["bun", "run", `app:${subcommand}:browser:${appSlug}`]);
|
|
1402
1402
|
return { ok: true, group: "browser", command: `${command}-${subcommand}` };
|
|
1403
1403
|
}
|
|
@@ -1409,7 +1409,7 @@ ${browserHelpText()}`);
|
|
|
1409
1409
|
};
|
|
1410
1410
|
const packageScript = packageScripts[command];
|
|
1411
1411
|
if (packageScript) {
|
|
1412
|
-
requireNoExtraArgs(rest, `
|
|
1412
|
+
requireNoExtraArgs(rest, `rig browser ${command}`);
|
|
1413
1413
|
await context.runCommand(["bun", "run", "--filter=@rig/browser", packageScript]);
|
|
1414
1414
|
return { ok: true, group: "browser", command };
|
|
1415
1415
|
}
|
|
@@ -1436,7 +1436,7 @@ async function executeBrowserDemo(context, args) {
|
|
|
1436
1436
|
pending = keepOpenFlag.rest;
|
|
1437
1437
|
const noBuildFlag = takeFlag(pending, "--no-build");
|
|
1438
1438
|
pending = noBuildFlag.rest;
|
|
1439
|
-
requireNoExtraArgs(pending, "
|
|
1439
|
+
requireNoExtraArgs(pending, "rig browser demo [--port <n>] [--profile <name>] [--state-dir <path>] [--target-url <url>] [--keep-open] [--no-build]");
|
|
1440
1440
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1441
1441
|
throw new CliError2("rig browser demo requires an interactive TTY in text mode.");
|
|
1442
1442
|
}
|
|
@@ -1947,17 +1947,17 @@ async function executeProfile(context, args) {
|
|
|
1947
1947
|
const [command = "show", ...rest] = args;
|
|
1948
1948
|
switch (command) {
|
|
1949
1949
|
case "show":
|
|
1950
|
-
requireNoExtraArgs(rest, "
|
|
1950
|
+
requireNoExtraArgs(rest, "rig profile show");
|
|
1951
1951
|
await withMutedConsole(context.outputMode === "json", () => showProfile(context.projectRoot));
|
|
1952
1952
|
return { ok: true, group: "profile", command };
|
|
1953
1953
|
case "set": {
|
|
1954
1954
|
if (rest.length === 0) {
|
|
1955
|
-
throw new CliError2("Usage:
|
|
1955
|
+
throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi> or set [--model ...] [--runtime ...] [--plugin ...]");
|
|
1956
1956
|
}
|
|
1957
1957
|
const preset = rest[0];
|
|
1958
1958
|
if (preset && !preset.startsWith("-")) {
|
|
1959
1959
|
if (rest.length !== 1) {
|
|
1960
|
-
throw new CliError2("Usage:
|
|
1960
|
+
throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi>");
|
|
1961
1961
|
}
|
|
1962
1962
|
try {
|
|
1963
1963
|
await withMutedConsole(context.outputMode === "json", () => setProfile(context.projectRoot, { preset }));
|
|
@@ -1973,7 +1973,7 @@ async function executeProfile(context, args) {
|
|
|
1973
1973
|
pending = runtimeResult.rest;
|
|
1974
1974
|
const pluginResult = takeOption(pending, "--plugin");
|
|
1975
1975
|
pending = pluginResult.rest;
|
|
1976
|
-
requireNoExtraArgs(pending, "
|
|
1976
|
+
requireNoExtraArgs(pending, "rig profile set [--model ...] [--runtime ...] [--plugin ...]");
|
|
1977
1977
|
if (!modelResult.value && !runtimeResult.value && !pluginResult.value) {
|
|
1978
1978
|
throw new CliError2("Provide at least one of --model, --runtime, or --plugin.");
|
|
1979
1979
|
}
|
|
@@ -2005,21 +2005,21 @@ async function executeReview(context, args) {
|
|
|
2005
2005
|
const [command = "show", ...rest] = args;
|
|
2006
2006
|
switch (command) {
|
|
2007
2007
|
case "show":
|
|
2008
|
-
requireNoExtraArgs(rest, "
|
|
2008
|
+
requireNoExtraArgs(rest, "rig review show");
|
|
2009
2009
|
await withMutedConsole(context.outputMode === "json", () => showReviewProfile(context.projectRoot));
|
|
2010
2010
|
return { ok: true, group: "review", command };
|
|
2011
2011
|
case "set": {
|
|
2012
2012
|
if (rest.length === 0) {
|
|
2013
|
-
throw new CliError2("Usage:
|
|
2013
|
+
throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
|
|
2014
2014
|
}
|
|
2015
2015
|
const mode = rest[0];
|
|
2016
2016
|
if (!mode) {
|
|
2017
|
-
throw new CliError2("Usage:
|
|
2017
|
+
throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
|
|
2018
2018
|
}
|
|
2019
2019
|
let pending = rest.slice(1);
|
|
2020
2020
|
const providerResult = takeOption(pending, "--provider");
|
|
2021
2021
|
pending = providerResult.rest;
|
|
2022
|
-
requireNoExtraArgs(pending, "
|
|
2022
|
+
requireNoExtraArgs(pending, "rig review set <off|advisory|required> [--provider greptile]");
|
|
2023
2023
|
try {
|
|
2024
2024
|
await withMutedConsole(context.outputMode === "json", () => {
|
|
2025
2025
|
return setReviewProfile(context.projectRoot, mode, providerResult.value);
|
|
@@ -2104,13 +2104,13 @@ async function executeRepo(context, args) {
|
|
|
2104
2104
|
switch (command) {
|
|
2105
2105
|
case "sync": {
|
|
2106
2106
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
2107
|
-
requireNoExtraArgs(remaining, "
|
|
2107
|
+
requireNoExtraArgs(remaining, "rig repo sync [--task <task-id>]");
|
|
2108
2108
|
withMutedConsole(context.outputMode === "json", () => repoEnsure(context.projectRoot, task || undefined));
|
|
2109
2109
|
return { ok: true, group: "repo", command, details: { task: task || null } };
|
|
2110
2110
|
}
|
|
2111
2111
|
case "reset-baseline": {
|
|
2112
2112
|
const { value: keepTaskStatusFlag, rest: remaining } = takeFlag(rest, "--keep-task-status");
|
|
2113
|
-
requireNoExtraArgs(remaining, "
|
|
2113
|
+
requireNoExtraArgs(remaining, "rig repo reset-baseline [--keep-task-status]");
|
|
2114
2114
|
withMutedConsole(context.outputMode === "json", () => resetBaseline(context.projectRoot, keepTaskStatusFlag));
|
|
2115
2115
|
return { ok: true, group: "repo", command, details: { keepTaskStatus: keepTaskStatusFlag } };
|
|
2116
2116
|
}
|
|
@@ -2120,7 +2120,7 @@ async function executeRepo(context, args) {
|
|
|
2120
2120
|
}
|
|
2121
2121
|
async function executeGit(context, args) {
|
|
2122
2122
|
if (args.length === 0) {
|
|
2123
|
-
throw new CliError2("Usage:
|
|
2123
|
+
throw new CliError2("Usage: rig git <git-flow args...>");
|
|
2124
2124
|
}
|
|
2125
2125
|
await enforceNativeCommandPolicy(context, args, {
|
|
2126
2126
|
commandPrefix: "rig-agent git",
|
|
@@ -2141,7 +2141,7 @@ async function executeGit(context, args) {
|
|
|
2141
2141
|
}
|
|
2142
2142
|
async function executeHarness(context, args) {
|
|
2143
2143
|
if (args.length === 0) {
|
|
2144
|
-
throw new CliError2("Usage:
|
|
2144
|
+
throw new CliError2("Usage: rig harness <harness args...>");
|
|
2145
2145
|
}
|
|
2146
2146
|
await enforceNativeCommandPolicy(context, args, {
|
|
2147
2147
|
commandPrefix: "rig-agent",
|
|
@@ -2250,7 +2250,7 @@ async function executePlugin(context, args) {
|
|
|
2250
2250
|
const [command = "list", ...rest] = args;
|
|
2251
2251
|
switch (command) {
|
|
2252
2252
|
case "list": {
|
|
2253
|
-
requireNoExtraArgs(rest, "
|
|
2253
|
+
requireNoExtraArgs(rest, "rig plugin list");
|
|
2254
2254
|
const legacyPlugins = context.plugins.list();
|
|
2255
2255
|
const declarative = [];
|
|
2256
2256
|
const config = await loadRigConfigOrNull(context.projectRoot);
|
|
@@ -2317,8 +2317,8 @@ async function executePlugin(context, args) {
|
|
|
2317
2317
|
}
|
|
2318
2318
|
case "validate": {
|
|
2319
2319
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
2320
|
-
requireNoExtraArgs(remaining, "
|
|
2321
|
-
const taskId = requireTask(task, "
|
|
2320
|
+
requireNoExtraArgs(remaining, "rig plugin validate --task <task-id>");
|
|
2321
|
+
const taskId = requireTask(task, "rig plugin validate --task <task-id>");
|
|
2322
2322
|
const results = await context.plugins.runValidators(taskId);
|
|
2323
2323
|
const passed = results.filter((result) => result.passed).length;
|
|
2324
2324
|
const failed = results.length - passed;
|
|
@@ -2458,7 +2458,7 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
2458
2458
|
const global = readGlobalConnections(options);
|
|
2459
2459
|
const connection = global.connections[repo.selected];
|
|
2460
2460
|
if (!connection) {
|
|
2461
|
-
throw new CliError2(`Selected Rig
|
|
2461
|
+
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
2462
2462
|
}
|
|
2463
2463
|
return { alias: repo.selected, connection };
|
|
2464
2464
|
}
|
|
@@ -2950,7 +2950,7 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
2950
2950
|
}
|
|
2951
2951
|
}
|
|
2952
2952
|
const repo = readRepoConnection(context.projectRoot);
|
|
2953
|
-
checks.push(repo ? preflightCheck("project-link", "project linked to Rig
|
|
2953
|
+
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>`."));
|
|
2954
2954
|
try {
|
|
2955
2955
|
const auth = await request("/api/github/auth/status");
|
|
2956
2956
|
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>`."));
|
|
@@ -3068,7 +3068,7 @@ async function executeQueue(context, args) {
|
|
|
3068
3068
|
pending = failFastResult.rest;
|
|
3069
3069
|
const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
|
|
3070
3070
|
pending = skipProjectSyncResult.rest;
|
|
3071
|
-
requireNoExtraArgs(pending, "
|
|
3071
|
+
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]");
|
|
3072
3072
|
const workers = parsePositiveInt(workersResult.value, "--workers", 2);
|
|
3073
3073
|
const maxTasks = parsePositiveInt(maxTasksResult.value, "--max-tasks", 10);
|
|
3074
3074
|
const action = parseAction(actionResult.value);
|
|
@@ -3246,7 +3246,7 @@ async function executeAgent(context, args) {
|
|
|
3246
3246
|
const [command = "list", ...rest] = args;
|
|
3247
3247
|
switch (command) {
|
|
3248
3248
|
case "list": {
|
|
3249
|
-
requireNoExtraArgs(rest, "
|
|
3249
|
+
requireNoExtraArgs(rest, "rig agent list");
|
|
3250
3250
|
const runtimes = await listAgentRuntimes(context.projectRoot);
|
|
3251
3251
|
if (context.outputMode === "text") {
|
|
3252
3252
|
if (runtimes.length === 0) {
|
|
@@ -3267,12 +3267,12 @@ async function executeAgent(context, args) {
|
|
|
3267
3267
|
pending = modeResult.rest;
|
|
3268
3268
|
const taskResult = takeOption(pending, "--task");
|
|
3269
3269
|
pending = taskResult.rest;
|
|
3270
|
-
requireNoExtraArgs(pending, "
|
|
3270
|
+
requireNoExtraArgs(pending, "rig agent prepare --task <id> [--id <id>] [--mode worktree]");
|
|
3271
3271
|
const mode = parseIsolationMode(modeResult.value, false);
|
|
3272
3272
|
const id = idResult.value || agentId("agent");
|
|
3273
3273
|
const taskId = taskResult.value?.trim();
|
|
3274
3274
|
if (!taskId) {
|
|
3275
|
-
throw new CliError2("Usage:
|
|
3275
|
+
throw new CliError2("Usage: rig agent prepare --task <id> [--id <id>] [--mode worktree]");
|
|
3276
3276
|
}
|
|
3277
3277
|
const runtime = await withMutedConsole(context.outputMode === "json", () => ensureAgentRuntime({
|
|
3278
3278
|
projectRoot: context.projectRoot,
|
|
@@ -3290,7 +3290,7 @@ async function executeAgent(context, args) {
|
|
|
3290
3290
|
case "run": {
|
|
3291
3291
|
const { options, commandParts } = splitAtDoubleDash(rest);
|
|
3292
3292
|
if (commandParts.length === 0) {
|
|
3293
|
-
throw new CliError2("Usage:
|
|
3293
|
+
throw new CliError2("Usage: rig agent run [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3294
3294
|
}
|
|
3295
3295
|
let pending = options;
|
|
3296
3296
|
const idResult = takeOption(pending, "--id");
|
|
@@ -3301,12 +3301,12 @@ async function executeAgent(context, args) {
|
|
|
3301
3301
|
pending = taskResult.rest;
|
|
3302
3302
|
const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
|
|
3303
3303
|
pending = skipProjectSyncResult.rest;
|
|
3304
|
-
requireNoExtraArgs(pending, "
|
|
3304
|
+
requireNoExtraArgs(pending, "rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3305
3305
|
const mode = parseIsolationMode(modeResult.value, false);
|
|
3306
3306
|
const id = idResult.value || agentId("agent-run");
|
|
3307
3307
|
const taskId = taskResult.value?.trim();
|
|
3308
3308
|
if (!taskId) {
|
|
3309
|
-
throw new CliError2("Usage:
|
|
3309
|
+
throw new CliError2("Usage: rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3310
3310
|
}
|
|
3311
3311
|
await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
|
|
3312
3312
|
const createdAt = new Date().toISOString();
|
|
@@ -3420,7 +3420,7 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
|
|
|
3420
3420
|
pending = allResult.rest;
|
|
3421
3421
|
const idResult = takeOption(pending, "--id");
|
|
3422
3422
|
pending = idResult.rest;
|
|
3423
|
-
requireNoExtraArgs(pending, "
|
|
3423
|
+
requireNoExtraArgs(pending, "rig agent cleanup (--id <id> | --all)");
|
|
3424
3424
|
if (!allResult.value && !idResult.value) {
|
|
3425
3425
|
throw new CliError2("Provide --id <id> or --all.");
|
|
3426
3426
|
}
|
|
@@ -3556,7 +3556,7 @@ async function executeDist(context, args) {
|
|
|
3556
3556
|
switch (command) {
|
|
3557
3557
|
case "build": {
|
|
3558
3558
|
const { value: outputDir, rest: pending } = takeOption(rest, "--output-dir");
|
|
3559
|
-
requireNoExtraArgs(pending, "
|
|
3559
|
+
requireNoExtraArgs(pending, "rig dist build [--output-dir <dir>]");
|
|
3560
3560
|
const commandParts = ["bun", "run", "packages/cli/bin/build-rig-binaries.ts"];
|
|
3561
3561
|
if (outputDir) {
|
|
3562
3562
|
commandParts.push("--output-dir", outputDir);
|
|
@@ -3570,7 +3570,7 @@ async function executeDist(context, args) {
|
|
|
3570
3570
|
pending = scopeResult.rest;
|
|
3571
3571
|
const pathResult = takeOption(pending, "--path");
|
|
3572
3572
|
pending = pathResult.rest;
|
|
3573
|
-
requireNoExtraArgs(pending, "
|
|
3573
|
+
requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
|
|
3574
3574
|
const scope = parseInstallScope(scopeResult.value);
|
|
3575
3575
|
const installDir = resolveInstallDir(scope, pathResult.value);
|
|
3576
3576
|
mkdirSync5(installDir, { recursive: true });
|
|
@@ -3613,7 +3613,7 @@ async function executeDist(context, args) {
|
|
|
3613
3613
|
};
|
|
3614
3614
|
}
|
|
3615
3615
|
case "doctor": {
|
|
3616
|
-
requireNoExtraArgs(rest, "
|
|
3616
|
+
requireNoExtraArgs(rest, "rig dist doctor");
|
|
3617
3617
|
const details = await runDistDoctor(context.projectRoot);
|
|
3618
3618
|
if (context.outputMode === "text") {
|
|
3619
3619
|
console.log(`bun: ${details.bun.available ? `ok (${details.bun.version})` : "missing"}`);
|
|
@@ -3624,7 +3624,7 @@ async function executeDist(context, args) {
|
|
|
3624
3624
|
return { ok: true, group: "dist", command, details };
|
|
3625
3625
|
}
|
|
3626
3626
|
case "rebuild-agent": {
|
|
3627
|
-
requireNoExtraArgs(rest, "
|
|
3627
|
+
requireNoExtraArgs(rest, "rig dist rebuild-agent");
|
|
3628
3628
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
3629
3629
|
const currentId = computeRuntimeImageId(fp);
|
|
3630
3630
|
const imagesDir = resolve11(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
@@ -3776,6 +3776,414 @@ import {
|
|
|
3776
3776
|
readJsonlFile as readJsonlFile3,
|
|
3777
3777
|
resolveAuthorityRunDir as resolveAuthorityRunDir2
|
|
3778
3778
|
} from "@rig/runtime/control-plane/authority-files";
|
|
3779
|
+
|
|
3780
|
+
// packages/cli/src/commands/_cli-format.ts
|
|
3781
|
+
import { log as log3, note as note3 } from "@clack/prompts";
|
|
3782
|
+
import pc3 from "picocolors";
|
|
3783
|
+
function stringField(record, key, fallback = "") {
|
|
3784
|
+
const value = record[key];
|
|
3785
|
+
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
3786
|
+
}
|
|
3787
|
+
function numberField(record, key) {
|
|
3788
|
+
const value = record[key];
|
|
3789
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
3790
|
+
}
|
|
3791
|
+
function arrayField(record, key) {
|
|
3792
|
+
const value = record[key];
|
|
3793
|
+
return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
|
|
3794
|
+
}
|
|
3795
|
+
function rawObject(record) {
|
|
3796
|
+
const raw = record.raw;
|
|
3797
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
3798
|
+
}
|
|
3799
|
+
function truncate(value, width) {
|
|
3800
|
+
if (value.length <= width)
|
|
3801
|
+
return value;
|
|
3802
|
+
if (width <= 1)
|
|
3803
|
+
return "\u2026";
|
|
3804
|
+
return `${value.slice(0, width - 1)}\u2026`;
|
|
3805
|
+
}
|
|
3806
|
+
function pad(value, width) {
|
|
3807
|
+
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
3808
|
+
}
|
|
3809
|
+
function statusColor(status) {
|
|
3810
|
+
const normalized = status.toLowerCase();
|
|
3811
|
+
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
|
|
3812
|
+
return pc3.green;
|
|
3813
|
+
if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
|
|
3814
|
+
return pc3.red;
|
|
3815
|
+
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
3816
|
+
return pc3.cyan;
|
|
3817
|
+
if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
|
|
3818
|
+
return pc3.yellow;
|
|
3819
|
+
return pc3.dim;
|
|
3820
|
+
}
|
|
3821
|
+
function compactDate(value) {
|
|
3822
|
+
if (!value.trim())
|
|
3823
|
+
return "";
|
|
3824
|
+
const parsed = Date.parse(value);
|
|
3825
|
+
if (!Number.isFinite(parsed))
|
|
3826
|
+
return value;
|
|
3827
|
+
return new Date(parsed).toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "Z");
|
|
3828
|
+
}
|
|
3829
|
+
function compactValue(value) {
|
|
3830
|
+
if (value === null || value === undefined)
|
|
3831
|
+
return "";
|
|
3832
|
+
if (typeof value === "string")
|
|
3833
|
+
return value;
|
|
3834
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
3835
|
+
return String(value);
|
|
3836
|
+
if (Array.isArray(value))
|
|
3837
|
+
return value.map(compactValue).filter(Boolean).join(", ");
|
|
3838
|
+
return JSON.stringify(value);
|
|
3839
|
+
}
|
|
3840
|
+
function firstString(record, keys, fallback = "") {
|
|
3841
|
+
for (const key of keys) {
|
|
3842
|
+
const value = stringField(record, key);
|
|
3843
|
+
if (value)
|
|
3844
|
+
return value;
|
|
3845
|
+
}
|
|
3846
|
+
return fallback;
|
|
3847
|
+
}
|
|
3848
|
+
function runIdOf(run) {
|
|
3849
|
+
return firstString(run, ["runId", "id"], "(unknown-run)");
|
|
3850
|
+
}
|
|
3851
|
+
function taskIdOf(run) {
|
|
3852
|
+
return firstString(run, ["taskId", "task", "task_id"]);
|
|
3853
|
+
}
|
|
3854
|
+
function runTitleOf(run) {
|
|
3855
|
+
return firstString(run, ["title", "summary", "name"], taskIdOf(run) || "(untitled)");
|
|
3856
|
+
}
|
|
3857
|
+
function requestIdOf(entry) {
|
|
3858
|
+
return firstString(entry, ["requestId", "id", "approvalId", "inputId"], "(unknown-request)");
|
|
3859
|
+
}
|
|
3860
|
+
function shouldUseClackOutput() {
|
|
3861
|
+
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
3862
|
+
}
|
|
3863
|
+
function printFormattedOutput(message2, options = {}) {
|
|
3864
|
+
if (!shouldUseClackOutput()) {
|
|
3865
|
+
console.log(message2);
|
|
3866
|
+
return;
|
|
3867
|
+
}
|
|
3868
|
+
if (options.title)
|
|
3869
|
+
note3(message2, options.title);
|
|
3870
|
+
else
|
|
3871
|
+
log3.message(message2);
|
|
3872
|
+
}
|
|
3873
|
+
function formatStatusPill(status) {
|
|
3874
|
+
const label = status || "unknown";
|
|
3875
|
+
return statusColor(label)(`\u25CF ${label}`);
|
|
3876
|
+
}
|
|
3877
|
+
function formatSection(title, subtitle) {
|
|
3878
|
+
return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
3879
|
+
}
|
|
3880
|
+
function formatSuccessCard(title, rows = []) {
|
|
3881
|
+
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}`);
|
|
3882
|
+
return [formatSection(title), ...body].join(`
|
|
3883
|
+
`);
|
|
3884
|
+
}
|
|
3885
|
+
function formatNextSteps(steps) {
|
|
3886
|
+
if (steps.length === 0)
|
|
3887
|
+
return [];
|
|
3888
|
+
return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
|
|
3889
|
+
}
|
|
3890
|
+
function formatTaskList(tasks, options = {}) {
|
|
3891
|
+
if (options.raw)
|
|
3892
|
+
return tasks.map((task) => JSON.stringify(task)).join(`
|
|
3893
|
+
`);
|
|
3894
|
+
if (tasks.length === 0)
|
|
3895
|
+
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(`
|
|
3896
|
+
`);
|
|
3897
|
+
const rows = tasks.map((task) => {
|
|
3898
|
+
const raw = rawObject(task);
|
|
3899
|
+
const id = stringField(task, "id", "<unknown>");
|
|
3900
|
+
const status = stringField(task, "status", "unknown");
|
|
3901
|
+
const title = stringField(task, "title", "Untitled task");
|
|
3902
|
+
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
3903
|
+
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
3904
|
+
return { id, status, title, source, labels };
|
|
3905
|
+
});
|
|
3906
|
+
const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
|
|
3907
|
+
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
3908
|
+
const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
3909
|
+
const body = rows.map((row) => {
|
|
3910
|
+
const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
|
|
3911
|
+
const source = row.source ? pc3.dim(` ${row.source}`) : "";
|
|
3912
|
+
return [
|
|
3913
|
+
pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
|
|
3914
|
+
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
3915
|
+
`${row.title}${labels}${source}`
|
|
3916
|
+
].join(" ");
|
|
3917
|
+
});
|
|
3918
|
+
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(`
|
|
3919
|
+
`);
|
|
3920
|
+
}
|
|
3921
|
+
function formatTaskCard(task, options = {}) {
|
|
3922
|
+
const raw = rawObject(task);
|
|
3923
|
+
const id = stringField(task, "id", stringField(raw, "id", "<unknown>"));
|
|
3924
|
+
const status = stringField(task, "status", stringField(raw, "status", "unknown"));
|
|
3925
|
+
const title = stringField(task, "title", stringField(raw, "title", "Untitled task"));
|
|
3926
|
+
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
3927
|
+
const url = stringField(task, "url", stringField(raw, "url", ""));
|
|
3928
|
+
const number = numberField(task, "number") ?? numberField(raw, "number");
|
|
3929
|
+
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
3930
|
+
const assignees = arrayField(task, "assignees").length > 0 ? arrayField(task, "assignees") : arrayField(raw, "assignees");
|
|
3931
|
+
const readiness = compactValue(task.readiness ?? raw.readiness);
|
|
3932
|
+
const validators = compactValue(task.validators ?? raw.validators ?? task.validation ?? raw.validation);
|
|
3933
|
+
const rows = [
|
|
3934
|
+
["task", pc3.bold(id)],
|
|
3935
|
+
["status", formatStatusPill(status)],
|
|
3936
|
+
["title", title],
|
|
3937
|
+
["source", source],
|
|
3938
|
+
["number", number],
|
|
3939
|
+
["labels", labels.length ? labels.map((label) => `#${label}`).join(" ") : ""],
|
|
3940
|
+
["assignees", assignees.join(", ")],
|
|
3941
|
+
["readiness", readiness],
|
|
3942
|
+
["validators", validators],
|
|
3943
|
+
["url", url]
|
|
3944
|
+
];
|
|
3945
|
+
return [
|
|
3946
|
+
formatSuccessCard(options.title ?? (options.selected ? "Selected task" : "Task"), rows),
|
|
3947
|
+
"",
|
|
3948
|
+
...formatNextSteps([`Start: \`rig task run ${id}\``, `Details: \`rig task show ${id} --raw\``])
|
|
3949
|
+
].join(`
|
|
3950
|
+
`);
|
|
3951
|
+
}
|
|
3952
|
+
function formatTaskDetails(task) {
|
|
3953
|
+
return formatTaskCard(task, { title: "Task details" });
|
|
3954
|
+
}
|
|
3955
|
+
function formatRunList(runs, options = {}) {
|
|
3956
|
+
if (runs.length === 0) {
|
|
3957
|
+
return [
|
|
3958
|
+
formatSection("Runs", "none recorded"),
|
|
3959
|
+
options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
|
|
3960
|
+
"",
|
|
3961
|
+
...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
|
|
3962
|
+
].join(`
|
|
3963
|
+
`);
|
|
3964
|
+
}
|
|
3965
|
+
const rows = runs.map((run) => {
|
|
3966
|
+
const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
|
|
3967
|
+
const status = stringField(run, "status", "unknown");
|
|
3968
|
+
const taskId = stringField(run, "taskId", "");
|
|
3969
|
+
const title = stringField(run, "title", taskId || "(untitled)");
|
|
3970
|
+
const runtime = stringField(run, "runtimeAdapter", "");
|
|
3971
|
+
return { runId, status, title, runtime };
|
|
3972
|
+
});
|
|
3973
|
+
const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
|
|
3974
|
+
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
3975
|
+
const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
3976
|
+
const body = rows.map((row) => [
|
|
3977
|
+
pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
|
|
3978
|
+
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
3979
|
+
`${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
|
|
3980
|
+
].join(" "));
|
|
3981
|
+
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(`
|
|
3982
|
+
`);
|
|
3983
|
+
}
|
|
3984
|
+
function formatSubmittedRun(input) {
|
|
3985
|
+
const rows = [["run", pc3.bold(input.runId)]];
|
|
3986
|
+
if (input.task) {
|
|
3987
|
+
const id = stringField(input.task, "id", "<unknown>");
|
|
3988
|
+
const status = stringField(input.task, "status", "unknown");
|
|
3989
|
+
const title = stringField(input.task, "title", "Untitled task");
|
|
3990
|
+
rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
|
|
3991
|
+
}
|
|
3992
|
+
const runtime = [input.runtimeAdapter || "pi", input.runtimeMode || "full-access", input.interactionMode || "default"].filter(Boolean).join(" \xB7 ");
|
|
3993
|
+
rows.push(["runtime", runtime]);
|
|
3994
|
+
return [
|
|
3995
|
+
formatSuccessCard("Run submitted", rows),
|
|
3996
|
+
"",
|
|
3997
|
+
...formatNextSteps([
|
|
3998
|
+
`Attach: \`rig run attach ${input.runId} --follow\``,
|
|
3999
|
+
`Inspect: \`rig run show ${input.runId}\``,
|
|
4000
|
+
input.detached ? "Submitted detached; attach when you are ready." : "Interactive mode opens the native bundled Pi frontend."
|
|
4001
|
+
])
|
|
4002
|
+
].join(`
|
|
4003
|
+
`);
|
|
4004
|
+
}
|
|
4005
|
+
function formatRunCard(run, options = {}) {
|
|
4006
|
+
const raw = rawObject(run);
|
|
4007
|
+
const merged = { ...raw, ...run };
|
|
4008
|
+
const runId = runIdOf(merged);
|
|
4009
|
+
const status = firstString(merged, ["status"], "unknown");
|
|
4010
|
+
const taskId = taskIdOf(merged);
|
|
4011
|
+
const title = runTitleOf(merged);
|
|
4012
|
+
const runtime = firstString(merged, ["runtimeAdapter", "runtime", "adapter"]);
|
|
4013
|
+
const mode = firstString(merged, ["runtimeMode", "mode"]);
|
|
4014
|
+
const interaction = firstString(merged, ["interactionMode"]);
|
|
4015
|
+
const created = compactDate(firstString(merged, ["createdAt"]));
|
|
4016
|
+
const started = compactDate(firstString(merged, ["startedAt"]));
|
|
4017
|
+
const updated = compactDate(firstString(merged, ["updatedAt"]));
|
|
4018
|
+
const completed = compactDate(firstString(merged, ["completedAt", "finishedAt"]));
|
|
4019
|
+
const worktree = firstString(merged, ["worktreePath", "cwd", "projectRoot"]);
|
|
4020
|
+
const piSession = merged.piSession && typeof merged.piSession === "object" && !Array.isArray(merged.piSession) ? firstString(merged.piSession, ["sessionId", "id"]) : "";
|
|
4021
|
+
const timeline = Array.isArray(merged.timeline) ? merged.timeline.length : null;
|
|
4022
|
+
const approvals = Array.isArray(merged.approvals) ? merged.approvals.length : null;
|
|
4023
|
+
const inputs = Array.isArray(merged.userInputs) ? merged.userInputs.length : null;
|
|
4024
|
+
const rows = [
|
|
4025
|
+
["run", pc3.bold(runId)],
|
|
4026
|
+
["status", formatStatusPill(status)],
|
|
4027
|
+
["task", taskId],
|
|
4028
|
+
["title", title],
|
|
4029
|
+
["runtime", [runtime, mode, interaction].filter(Boolean).join(" \xB7 ")],
|
|
4030
|
+
["created", created],
|
|
4031
|
+
["started", started],
|
|
4032
|
+
["updated", updated],
|
|
4033
|
+
["completed", completed],
|
|
4034
|
+
["worktree", worktree],
|
|
4035
|
+
["pi", piSession],
|
|
4036
|
+
["timeline", timeline],
|
|
4037
|
+
["approvals", approvals],
|
|
4038
|
+
["inputs", inputs]
|
|
4039
|
+
];
|
|
4040
|
+
return [
|
|
4041
|
+
formatSuccessCard(options.title ?? "Run details", rows),
|
|
4042
|
+
"",
|
|
4043
|
+
...formatNextSteps([`Follow live: \`rig run attach ${runId} --follow\``, `Raw payload: \`rig run show ${runId} --raw\``])
|
|
4044
|
+
].join(`
|
|
4045
|
+
`);
|
|
4046
|
+
}
|
|
4047
|
+
function formatRunStatus(summary, options = {}) {
|
|
4048
|
+
const activeRuns = summary.activeRuns ?? [];
|
|
4049
|
+
const recentRuns = summary.recentRuns ?? [];
|
|
4050
|
+
const lines = [formatSection("Run status", options.source === "server" ? "selected server" : "local state")];
|
|
4051
|
+
lines.push("", pc3.bold(`Active runs (${activeRuns.length})`));
|
|
4052
|
+
if (activeRuns.length === 0) {
|
|
4053
|
+
lines.push(pc3.dim("No active runs."));
|
|
4054
|
+
} else {
|
|
4055
|
+
for (const run of activeRuns) {
|
|
4056
|
+
lines.push(formatRunSummaryLine(run));
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
lines.push("", pc3.bold(`Recent runs (${recentRuns.length})`));
|
|
4060
|
+
if (recentRuns.length === 0) {
|
|
4061
|
+
lines.push(pc3.dim("No recent terminal runs."));
|
|
4062
|
+
} else {
|
|
4063
|
+
for (const run of recentRuns.slice(0, 10)) {
|
|
4064
|
+
lines.push(formatRunSummaryLine(run));
|
|
4065
|
+
}
|
|
4066
|
+
}
|
|
4067
|
+
lines.push("", ...formatNextSteps(["Start work: `rig task run --next`", "Attach: `rig run attach <run-id> --follow`", "Details: `rig run show <run-id>`"]));
|
|
4068
|
+
return lines.join(`
|
|
4069
|
+
`);
|
|
4070
|
+
}
|
|
4071
|
+
function formatRunSummaryLine(run) {
|
|
4072
|
+
const record = run;
|
|
4073
|
+
const runId = runIdOf(record);
|
|
4074
|
+
const status = firstString(record, ["status"], "unknown");
|
|
4075
|
+
const taskId = taskIdOf(record);
|
|
4076
|
+
const title = runTitleOf(record);
|
|
4077
|
+
const runtime = firstString(record, ["runtimeAdapter", "runtime", "adapter"]);
|
|
4078
|
+
const descriptor = [taskId, title].filter(Boolean).join(" \xB7 ");
|
|
4079
|
+
return `${pc3.dim("\u2502")} ${pc3.bold(runId)} ${formatStatusPill(status)} ${descriptor}${runtime ? pc3.dim(` ${runtime}`) : ""}`;
|
|
4080
|
+
}
|
|
4081
|
+
function formatInboxList(kind, entries) {
|
|
4082
|
+
const title = kind === "approvals" ? "Approval inbox" : "Input inbox";
|
|
4083
|
+
if (entries.length === 0) {
|
|
4084
|
+
return [
|
|
4085
|
+
formatSection(title, "empty"),
|
|
4086
|
+
pc3.dim(kind === "approvals" ? "No pending approvals." : "No pending user-input requests."),
|
|
4087
|
+
"",
|
|
4088
|
+
...formatNextSteps(["Check runs: `rig run status`", "Start work: `rig task run --next`"])
|
|
4089
|
+
].join(`
|
|
4090
|
+
`);
|
|
4091
|
+
}
|
|
4092
|
+
const lines = [formatSection(title, `${entries.length} pending`)];
|
|
4093
|
+
for (const entry of entries) {
|
|
4094
|
+
const record = entry.record && typeof entry.record === "object" && !Array.isArray(entry.record) ? entry.record : entry;
|
|
4095
|
+
const runId = firstString(entry, ["runId"], firstString(record, ["runId"]));
|
|
4096
|
+
const taskId = firstString(entry, ["taskId"], firstString(record, ["taskId", "task"]));
|
|
4097
|
+
const requestId = requestIdOf(record);
|
|
4098
|
+
const status = firstString(record, ["status", "state"], "pending");
|
|
4099
|
+
const prompt = firstString(record, ["prompt", "message", "reason", "title", "summary"], kind === "approvals" ? "Approval requested" : "Input requested");
|
|
4100
|
+
lines.push(`${pc3.dim("\u2502")} ${pc3.bold(requestId)} ${formatStatusPill(status)} ${prompt}`);
|
|
4101
|
+
lines.push(`${pc3.dim("\u2502")} ${pc3.dim("run ")} ${runId || "(unknown-run)"}${taskId ? pc3.dim(` task ${taskId}`) : ""}`);
|
|
4102
|
+
}
|
|
4103
|
+
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`"]));
|
|
4104
|
+
return lines.join(`
|
|
4105
|
+
`);
|
|
4106
|
+
}
|
|
4107
|
+
function formatConnectionList(connections) {
|
|
4108
|
+
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
4109
|
+
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
4110
|
+
const lines = rows.map(([alias, connection]) => [
|
|
4111
|
+
pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
4112
|
+
formatStatusPill(connection.kind),
|
|
4113
|
+
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
4114
|
+
].join(" "));
|
|
4115
|
+
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(`
|
|
4116
|
+
`);
|
|
4117
|
+
}
|
|
4118
|
+
function formatConnectionStatus(selected, connections) {
|
|
4119
|
+
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
4120
|
+
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
4121
|
+
return [
|
|
4122
|
+
formatSection("Rig server", "selected for this repo"),
|
|
4123
|
+
`${pc3.dim("\u2502")} ${pc3.dim("selected ")} ${pc3.bold(selected)}`,
|
|
4124
|
+
`${pc3.dim("\u2502")} ${pc3.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
4125
|
+
`${pc3.dim("\u2502")} ${pc3.dim("target ")} ${target ?? "not configured"}`,
|
|
4126
|
+
"",
|
|
4127
|
+
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
4128
|
+
].join(`
|
|
4129
|
+
`);
|
|
4130
|
+
}
|
|
4131
|
+
|
|
4132
|
+
// packages/cli/src/commands/inbox.ts
|
|
4133
|
+
function isRemoteConnectionSelected(projectRoot) {
|
|
4134
|
+
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
4135
|
+
}
|
|
4136
|
+
function runMatches(entry, filters) {
|
|
4137
|
+
const runId = typeof entry.runId === "string" ? entry.runId : typeof entry.id === "string" ? entry.id : "";
|
|
4138
|
+
const taskId = typeof entry.taskId === "string" ? entry.taskId : "";
|
|
4139
|
+
return (!filters.run || runId === filters.run) && (!filters.task || taskId === filters.task);
|
|
4140
|
+
}
|
|
4141
|
+
function normalizeRemoteRunDetails(payload) {
|
|
4142
|
+
const run = payload.run;
|
|
4143
|
+
if (run && typeof run === "object" && !Array.isArray(run)) {
|
|
4144
|
+
return {
|
|
4145
|
+
...run,
|
|
4146
|
+
...Array.isArray(payload.timeline) ? { timeline: payload.timeline } : {},
|
|
4147
|
+
...Array.isArray(payload.approvals) ? { approvals: payload.approvals } : {},
|
|
4148
|
+
...Array.isArray(payload.userInputs) ? { userInputs: payload.userInputs } : {}
|
|
4149
|
+
};
|
|
4150
|
+
}
|
|
4151
|
+
return payload;
|
|
4152
|
+
}
|
|
4153
|
+
function remoteRecordsFromRun(run, kind) {
|
|
4154
|
+
const key = kind === "approvals" ? "approvals" : "userInputs";
|
|
4155
|
+
const direct = run[key];
|
|
4156
|
+
if (!Array.isArray(direct))
|
|
4157
|
+
return [];
|
|
4158
|
+
const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
|
|
4159
|
+
const taskId = typeof run.taskId === "string" ? run.taskId : "";
|
|
4160
|
+
return direct.filter((record) => Boolean(record && typeof record === "object" && !Array.isArray(record))).map((record) => ({ runId, taskId, record }));
|
|
4161
|
+
}
|
|
4162
|
+
async function listRemoteInboxRecords(context, kind, filters) {
|
|
4163
|
+
const runs = (await listRunsViaServer(context, { limit: 100 })).filter((entry) => runMatches(entry, filters));
|
|
4164
|
+
const records = [];
|
|
4165
|
+
for (const run of runs) {
|
|
4166
|
+
const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
|
|
4167
|
+
const detailed = runId ? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => run)) : run;
|
|
4168
|
+
records.push(...remoteRecordsFromRun(detailed, kind));
|
|
4169
|
+
}
|
|
4170
|
+
return records;
|
|
4171
|
+
}
|
|
4172
|
+
function listLocalInboxRecords(context, kind, filters) {
|
|
4173
|
+
const fileName = kind === "approvals" ? "approvals.jsonl" : "user-input.jsonl";
|
|
4174
|
+
const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!filters.run || entry.runId === filters.run) && (!filters.task || entry.taskId === filters.task));
|
|
4175
|
+
return runs.flatMap((entry) => readJsonlFile3(resolve12(resolveAuthorityRunDir2(context.projectRoot, entry.runId), fileName)).map((record) => ({
|
|
4176
|
+
runId: entry.runId,
|
|
4177
|
+
taskId: entry.taskId ?? undefined,
|
|
4178
|
+
record
|
|
4179
|
+
})));
|
|
4180
|
+
}
|
|
4181
|
+
async function listInboxRecords(context, kind, filters) {
|
|
4182
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4183
|
+
return listRemoteInboxRecords(context, kind, filters);
|
|
4184
|
+
}
|
|
4185
|
+
return listLocalInboxRecords(context, kind, filters);
|
|
4186
|
+
}
|
|
3779
4187
|
async function executeInbox(context, args) {
|
|
3780
4188
|
const [command = "approvals", ...rest] = args;
|
|
3781
4189
|
switch (command) {
|
|
@@ -3785,16 +4193,10 @@ async function executeInbox(context, args) {
|
|
|
3785
4193
|
pending = run.rest;
|
|
3786
4194
|
const task = takeOption(pending, "--task");
|
|
3787
4195
|
pending = task.rest;
|
|
3788
|
-
requireNoExtraArgs(pending, "
|
|
3789
|
-
const
|
|
3790
|
-
const approvals = runs.flatMap((entry) => readJsonlFile3(resolve12(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "approvals.jsonl")).map((record) => ({
|
|
3791
|
-
runId: entry.runId,
|
|
3792
|
-
record
|
|
3793
|
-
})));
|
|
4196
|
+
requireNoExtraArgs(pending, "rig inbox approvals [--run <id>] [--task <id>]");
|
|
4197
|
+
const approvals = await listInboxRecords(context, "approvals", { run: run.value, task: task.value });
|
|
3794
4198
|
if (context.outputMode === "text") {
|
|
3795
|
-
|
|
3796
|
-
console.log(JSON.stringify(approval));
|
|
3797
|
-
}
|
|
4199
|
+
printFormattedOutput(formatInboxList("approvals", approvals));
|
|
3798
4200
|
}
|
|
3799
4201
|
return { ok: true, group: "inbox", command, details: { approvals } };
|
|
3800
4202
|
}
|
|
@@ -3806,19 +4208,22 @@ async function executeInbox(context, args) {
|
|
|
3806
4208
|
pending = request.rest;
|
|
3807
4209
|
const decision = takeOption(pending, "--decision");
|
|
3808
4210
|
pending = decision.rest;
|
|
3809
|
-
const
|
|
3810
|
-
pending =
|
|
3811
|
-
requireNoExtraArgs(pending, "
|
|
4211
|
+
const note4 = takeOption(pending, "--note");
|
|
4212
|
+
pending = note4.rest;
|
|
4213
|
+
requireNoExtraArgs(pending, "rig inbox approve --run <id> --request <id> --decision approve|reject [--note <text>]");
|
|
3812
4214
|
if (!run.value || !request.value || !decision.value) {
|
|
3813
4215
|
throw new CliError2("approve requires --run, --request, and --decision.");
|
|
3814
4216
|
}
|
|
3815
4217
|
if (decision.value !== "approve" && decision.value !== "reject") {
|
|
3816
4218
|
throw new CliError2("decision must be approve or reject.");
|
|
3817
4219
|
}
|
|
4220
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4221
|
+
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);
|
|
4222
|
+
}
|
|
3818
4223
|
const approvalsPath = resolve12(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
|
|
3819
4224
|
const approvals = readJsonlFile3(approvalsPath);
|
|
3820
4225
|
const resolvedAt = new Date().toISOString();
|
|
3821
|
-
const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note:
|
|
4226
|
+
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);
|
|
3822
4227
|
writeFileSync4(approvalsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
|
|
3823
4228
|
`)}
|
|
3824
4229
|
`, "utf8");
|
|
@@ -3830,16 +4235,10 @@ async function executeInbox(context, args) {
|
|
|
3830
4235
|
pending = run.rest;
|
|
3831
4236
|
const task = takeOption(pending, "--task");
|
|
3832
4237
|
pending = task.rest;
|
|
3833
|
-
requireNoExtraArgs(pending, "
|
|
3834
|
-
const
|
|
3835
|
-
const requests = runs.flatMap((entry) => readJsonlFile3(resolve12(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "user-input.jsonl")).map((record) => ({
|
|
3836
|
-
runId: entry.runId,
|
|
3837
|
-
record
|
|
3838
|
-
})));
|
|
4238
|
+
requireNoExtraArgs(pending, "rig inbox inputs [--run <id>] [--task <id>]");
|
|
4239
|
+
const requests = await listInboxRecords(context, "inputs", { run: run.value, task: task.value });
|
|
3839
4240
|
if (context.outputMode === "text") {
|
|
3840
|
-
|
|
3841
|
-
console.log(JSON.stringify(request));
|
|
3842
|
-
}
|
|
4241
|
+
printFormattedOutput(formatInboxList("inputs", requests));
|
|
3843
4242
|
}
|
|
3844
4243
|
return { ok: true, group: "inbox", command, details: { requests } };
|
|
3845
4244
|
}
|
|
@@ -3866,10 +4265,13 @@ async function executeInbox(context, args) {
|
|
|
3866
4265
|
remaining.push(current);
|
|
3867
4266
|
}
|
|
3868
4267
|
}
|
|
3869
|
-
requireNoExtraArgs(remaining, "
|
|
4268
|
+
requireNoExtraArgs(remaining, "rig inbox respond --run <id> --request <id> --answer key=value [--answer key=value]");
|
|
3870
4269
|
if (!run.value || !request.value || answers.length === 0) {
|
|
3871
4270
|
throw new CliError2("respond requires --run, --request, and at least one --answer.");
|
|
3872
4271
|
}
|
|
4272
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4273
|
+
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);
|
|
4274
|
+
}
|
|
3873
4275
|
const parsedAnswers = Object.fromEntries(answers.map((entry) => {
|
|
3874
4276
|
const [key, ...restValue] = entry.split("=");
|
|
3875
4277
|
return [key, restValue.join("=")];
|
|
@@ -4293,7 +4695,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4293
4695
|
const taskSourceKind = config?.taskSource?.kind;
|
|
4294
4696
|
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."));
|
|
4295
4697
|
const repo = readRepoConnection(projectRoot);
|
|
4296
|
-
checks.push(repo ? check("project-link", "repo selected Rig
|
|
4698
|
+
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>`."));
|
|
4297
4699
|
const selected = (() => {
|
|
4298
4700
|
try {
|
|
4299
4701
|
return resolveSelectedConnection(projectRoot);
|
|
@@ -4301,7 +4703,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4301
4703
|
return null;
|
|
4302
4704
|
}
|
|
4303
4705
|
})();
|
|
4304
|
-
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server
|
|
4706
|
+
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));
|
|
4305
4707
|
let server = null;
|
|
4306
4708
|
try {
|
|
4307
4709
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
@@ -5084,187 +5486,32 @@ async function runInteractiveControlPlaneInit(context, prompts) {
|
|
|
5084
5486
|
githubProjectStatusField: projectConfig.githubProjectStatusField,
|
|
5085
5487
|
githubProjectStatuses: projectConfig.githubProjectStatuses,
|
|
5086
5488
|
remoteCheckout,
|
|
5087
|
-
repair,
|
|
5088
|
-
privateStateOnly,
|
|
5089
|
-
yes: remoteGhTokenConfirmed || undefined
|
|
5090
|
-
});
|
|
5091
|
-
const details = result.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : {};
|
|
5092
|
-
const deviceAuth = details.deviceAuth && typeof details.deviceAuth === "object" && !Array.isArray(details.deviceAuth) ? details.deviceAuth : null;
|
|
5093
|
-
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")}.` : "";
|
|
5094
|
-
prompts.outro?.(`Rig project initialized.${deviceMessage} Next: rig doctor && rig task list`);
|
|
5095
|
-
return result;
|
|
5096
|
-
}
|
|
5097
|
-
async function executeInit(context, args) {
|
|
5098
|
-
const parsed = parseInitOptions(args);
|
|
5099
|
-
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) {
|
|
5100
|
-
if (parsed.rest.length > 0)
|
|
5101
|
-
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5102
|
-
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);
|
|
5103
|
-
return runControlPlaneInit(context, parsed.options);
|
|
5104
|
-
}
|
|
5105
|
-
if (parsed.rest.length > 0)
|
|
5106
|
-
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5107
|
-
Usage: rig init`, 1);
|
|
5108
|
-
return runInteractiveControlPlaneInit(context, await loadClackPrompts());
|
|
5109
|
-
}
|
|
5110
|
-
|
|
5111
|
-
// packages/cli/src/commands/connect.ts
|
|
5112
|
-
import { cancel as cancel2, isCancel as isCancel2, select as select2 } from "@clack/prompts";
|
|
5113
|
-
|
|
5114
|
-
// packages/cli/src/commands/_cli-format.ts
|
|
5115
|
-
import pc3 from "picocolors";
|
|
5116
|
-
function stringField(record, key, fallback = "") {
|
|
5117
|
-
const value = record[key];
|
|
5118
|
-
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
5119
|
-
}
|
|
5120
|
-
function arrayField(record, key) {
|
|
5121
|
-
const value = record[key];
|
|
5122
|
-
return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
|
|
5123
|
-
}
|
|
5124
|
-
function rawObject(record) {
|
|
5125
|
-
const raw = record.raw;
|
|
5126
|
-
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
5127
|
-
}
|
|
5128
|
-
function truncate(value, width) {
|
|
5129
|
-
if (value.length <= width)
|
|
5130
|
-
return value;
|
|
5131
|
-
if (width <= 1)
|
|
5132
|
-
return "\u2026";
|
|
5133
|
-
return `${value.slice(0, width - 1)}\u2026`;
|
|
5134
|
-
}
|
|
5135
|
-
function pad(value, width) {
|
|
5136
|
-
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
5137
|
-
}
|
|
5138
|
-
function statusColor(status) {
|
|
5139
|
-
const normalized = status.toLowerCase();
|
|
5140
|
-
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected"].includes(normalized))
|
|
5141
|
-
return pc3.green;
|
|
5142
|
-
if (["failed", "needs_attention", "needs-attention", "blocked", "error"].includes(normalized))
|
|
5143
|
-
return pc3.red;
|
|
5144
|
-
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
5145
|
-
return pc3.cyan;
|
|
5146
|
-
if (["ready", "open", "queued", "created", "preparing", "local"].includes(normalized))
|
|
5147
|
-
return pc3.yellow;
|
|
5148
|
-
return pc3.dim;
|
|
5149
|
-
}
|
|
5150
|
-
function formatStatusPill(status) {
|
|
5151
|
-
const label = status || "unknown";
|
|
5152
|
-
return statusColor(label)(`\u25CF ${label}`);
|
|
5153
|
-
}
|
|
5154
|
-
function formatSection(title, subtitle) {
|
|
5155
|
-
return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
5156
|
-
}
|
|
5157
|
-
function formatSuccessCard(title, rows = []) {
|
|
5158
|
-
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}`);
|
|
5159
|
-
return [formatSection(title), ...body].join(`
|
|
5160
|
-
`);
|
|
5161
|
-
}
|
|
5162
|
-
function formatNextSteps(steps) {
|
|
5163
|
-
if (steps.length === 0)
|
|
5164
|
-
return [];
|
|
5165
|
-
return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
|
|
5166
|
-
}
|
|
5167
|
-
function formatTaskList(tasks, options = {}) {
|
|
5168
|
-
if (options.raw)
|
|
5169
|
-
return tasks.map((task) => JSON.stringify(task)).join(`
|
|
5170
|
-
`);
|
|
5171
|
-
if (tasks.length === 0)
|
|
5172
|
-
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(`
|
|
5173
|
-
`);
|
|
5174
|
-
const rows = tasks.map((task) => {
|
|
5175
|
-
const raw = rawObject(task);
|
|
5176
|
-
const id = stringField(task, "id", "<unknown>");
|
|
5177
|
-
const status = stringField(task, "status", "unknown");
|
|
5178
|
-
const title = stringField(task, "title", "Untitled task");
|
|
5179
|
-
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
5180
|
-
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
5181
|
-
return { id, status, title, source, labels };
|
|
5182
|
-
});
|
|
5183
|
-
const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
|
|
5184
|
-
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
5185
|
-
const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
5186
|
-
const body = rows.map((row) => {
|
|
5187
|
-
const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
|
|
5188
|
-
const source = row.source ? pc3.dim(` ${row.source}`) : "";
|
|
5189
|
-
return [
|
|
5190
|
-
pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
|
|
5191
|
-
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
5192
|
-
`${row.title}${labels}${source}`
|
|
5193
|
-
].join(" ");
|
|
5194
|
-
});
|
|
5195
|
-
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(`
|
|
5196
|
-
`);
|
|
5197
|
-
}
|
|
5198
|
-
function formatRunList(runs, options = {}) {
|
|
5199
|
-
if (runs.length === 0) {
|
|
5200
|
-
return [
|
|
5201
|
-
formatSection("Runs", "none recorded"),
|
|
5202
|
-
options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
|
|
5203
|
-
"",
|
|
5204
|
-
...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
|
|
5205
|
-
].join(`
|
|
5206
|
-
`);
|
|
5207
|
-
}
|
|
5208
|
-
const rows = runs.map((run) => {
|
|
5209
|
-
const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
|
|
5210
|
-
const status = stringField(run, "status", "unknown");
|
|
5211
|
-
const taskId = stringField(run, "taskId", "");
|
|
5212
|
-
const title = stringField(run, "title", taskId || "(untitled)");
|
|
5213
|
-
const runtime = stringField(run, "runtimeAdapter", "");
|
|
5214
|
-
return { runId, status, title, runtime };
|
|
5215
|
-
});
|
|
5216
|
-
const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
|
|
5217
|
-
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
5218
|
-
const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
5219
|
-
const body = rows.map((row) => [
|
|
5220
|
-
pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
|
|
5221
|
-
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
5222
|
-
`${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
|
|
5223
|
-
].join(" "));
|
|
5224
|
-
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(`
|
|
5225
|
-
`);
|
|
5226
|
-
}
|
|
5227
|
-
function formatSubmittedRun(input) {
|
|
5228
|
-
const rows = [["run", pc3.bold(input.runId)]];
|
|
5229
|
-
if (input.task) {
|
|
5230
|
-
const id = stringField(input.task, "id", "<unknown>");
|
|
5231
|
-
const status = stringField(input.task, "status", "unknown");
|
|
5232
|
-
const title = stringField(input.task, "title", "Untitled task");
|
|
5233
|
-
rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
|
|
5234
|
-
}
|
|
5235
|
-
return [
|
|
5236
|
-
formatSuccessCard("Run submitted", rows),
|
|
5237
|
-
"",
|
|
5238
|
-
...formatNextSteps([`Attach: \`rig run attach ${input.runId} --follow\``, `Inspect: \`rig run show --run ${input.runId}\``])
|
|
5239
|
-
].join(`
|
|
5240
|
-
`);
|
|
5241
|
-
}
|
|
5242
|
-
function formatConnectionList(connections) {
|
|
5243
|
-
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
5244
|
-
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
5245
|
-
const lines = rows.map(([alias, connection]) => [
|
|
5246
|
-
pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
5247
|
-
formatStatusPill(connection.kind),
|
|
5248
|
-
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
5249
|
-
].join(" "));
|
|
5250
|
-
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(`
|
|
5251
|
-
`);
|
|
5489
|
+
repair,
|
|
5490
|
+
privateStateOnly,
|
|
5491
|
+
yes: remoteGhTokenConfirmed || undefined
|
|
5492
|
+
});
|
|
5493
|
+
const details = result.details && typeof result.details === "object" && !Array.isArray(result.details) ? result.details : {};
|
|
5494
|
+
const deviceAuth = details.deviceAuth && typeof details.deviceAuth === "object" && !Array.isArray(details.deviceAuth) ? details.deviceAuth : null;
|
|
5495
|
+
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")}.` : "";
|
|
5496
|
+
prompts.outro?.(`Rig project initialized.${deviceMessage} Next: rig doctor && rig task list`);
|
|
5497
|
+
return result;
|
|
5252
5498
|
}
|
|
5253
|
-
function
|
|
5254
|
-
const
|
|
5255
|
-
|
|
5256
|
-
|
|
5257
|
-
|
|
5258
|
-
|
|
5259
|
-
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
5263
|
-
|
|
5264
|
-
|
|
5499
|
+
async function executeInit(context, args) {
|
|
5500
|
+
const parsed = parseInitOptions(args);
|
|
5501
|
+
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) {
|
|
5502
|
+
if (parsed.rest.length > 0)
|
|
5503
|
+
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5504
|
+
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);
|
|
5505
|
+
return runControlPlaneInit(context, parsed.options);
|
|
5506
|
+
}
|
|
5507
|
+
if (parsed.rest.length > 0)
|
|
5508
|
+
throw new CliError2(`Unexpected arguments: ${parsed.rest.join(" ")}
|
|
5509
|
+
Usage: rig init`, 1);
|
|
5510
|
+
return runInteractiveControlPlaneInit(context, await loadClackPrompts());
|
|
5265
5511
|
}
|
|
5266
5512
|
|
|
5267
5513
|
// packages/cli/src/commands/connect.ts
|
|
5514
|
+
import { cancel as cancel2, isCancel as isCancel2, select as select2 } from "@clack/prompts";
|
|
5268
5515
|
function usageName(options) {
|
|
5269
5516
|
return `rig ${options.group}`;
|
|
5270
5517
|
}
|
|
@@ -5689,8 +5936,8 @@ async function executeInspect(context, args) {
|
|
|
5689
5936
|
switch (command) {
|
|
5690
5937
|
case "logs": {
|
|
5691
5938
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5692
|
-
requireNoExtraArgs(remaining, "
|
|
5693
|
-
const requiredTask = requireTask(task, "
|
|
5939
|
+
requireNoExtraArgs(remaining, "rig inspect logs --task <task-id>");
|
|
5940
|
+
const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
|
|
5694
5941
|
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];
|
|
5695
5942
|
if (!latestRun) {
|
|
5696
5943
|
throw new CliError2(`No runs found for ${requiredTask}.`);
|
|
@@ -5704,8 +5951,8 @@ async function executeInspect(context, args) {
|
|
|
5704
5951
|
}
|
|
5705
5952
|
case "artifacts": {
|
|
5706
5953
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5707
|
-
requireNoExtraArgs(remaining, "
|
|
5708
|
-
const requiredTask = requireTask(task, "
|
|
5954
|
+
requireNoExtraArgs(remaining, "rig inspect artifacts --task <task-id>");
|
|
5955
|
+
const requiredTask = requireTask(task, "rig inspect artifacts --task <task-id>");
|
|
5709
5956
|
const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync10(path));
|
|
5710
5957
|
if (!artifactRoot) {
|
|
5711
5958
|
throw new CliError2(`No artifacts found for ${requiredTask}.`);
|
|
@@ -5719,8 +5966,8 @@ async function executeInspect(context, args) {
|
|
|
5719
5966
|
previewPending = task.rest;
|
|
5720
5967
|
const file = takeOption(previewPending, "--file");
|
|
5721
5968
|
previewPending = file.rest;
|
|
5722
|
-
requireNoExtraArgs(previewPending, "
|
|
5723
|
-
const requiredTask = requireTask(task.value, "
|
|
5969
|
+
requireNoExtraArgs(previewPending, "rig inspect artifact --task <task-id> --file <name>");
|
|
5970
|
+
const requiredTask = requireTask(task.value, "rig inspect artifact --task <task-id> --file <name>");
|
|
5724
5971
|
if (!file.value) {
|
|
5725
5972
|
throw new CliError2("Missing --file for rig inspect artifact.");
|
|
5726
5973
|
}
|
|
@@ -5749,7 +5996,7 @@ async function executeInspect(context, args) {
|
|
|
5749
5996
|
}
|
|
5750
5997
|
case "diff": {
|
|
5751
5998
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5752
|
-
requireNoExtraArgs(remaining, "
|
|
5999
|
+
requireNoExtraArgs(remaining, "rig inspect diff [--task <task-id>]");
|
|
5753
6000
|
if (task) {
|
|
5754
6001
|
const files = changedFilesForTask(context.projectRoot, task, false);
|
|
5755
6002
|
for (const file of files) {
|
|
@@ -5761,7 +6008,7 @@ async function executeInspect(context, args) {
|
|
|
5761
6008
|
return { ok: true, group: "inspect", command, details: { task: task || null } };
|
|
5762
6009
|
}
|
|
5763
6010
|
case "failures": {
|
|
5764
|
-
requireNoExtraArgs(rest, "
|
|
6011
|
+
requireNoExtraArgs(rest, "rig inspect failures");
|
|
5765
6012
|
const failed = resolveHarnessPaths2(context.projectRoot).failedApproachesPath;
|
|
5766
6013
|
if (!existsSync10(failed)) {
|
|
5767
6014
|
console.log("No failures recorded.");
|
|
@@ -5771,7 +6018,7 @@ async function executeInspect(context, args) {
|
|
|
5771
6018
|
return { ok: true, group: "inspect", command };
|
|
5772
6019
|
}
|
|
5773
6020
|
case "graph":
|
|
5774
|
-
requireNoExtraArgs(rest, "
|
|
6021
|
+
requireNoExtraArgs(rest, "rig inspect graph");
|
|
5775
6022
|
{
|
|
5776
6023
|
const monorepoRoot = resolveMonorepoRoot2(context.projectRoot);
|
|
5777
6024
|
const result = runCapture3(["br", "--no-db", "list", "--pretty"], monorepoRoot);
|
|
@@ -5782,7 +6029,7 @@ async function executeInspect(context, args) {
|
|
|
5782
6029
|
}
|
|
5783
6030
|
return { ok: true, group: "inspect", command };
|
|
5784
6031
|
case "audit": {
|
|
5785
|
-
requireNoExtraArgs(rest, "
|
|
6032
|
+
requireNoExtraArgs(rest, "rig inspect audit");
|
|
5786
6033
|
const auditPath = resolve18(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
|
|
5787
6034
|
if (!existsSync10(auditPath)) {
|
|
5788
6035
|
console.log("No audit log found.");
|
|
@@ -5841,7 +6088,7 @@ async function executeInspector(context, args) {
|
|
|
5841
6088
|
pending = secondsResult.rest;
|
|
5842
6089
|
const pollMsResult = takeOption(pending, "--poll-ms");
|
|
5843
6090
|
pending = pollMsResult.rest;
|
|
5844
|
-
requireNoExtraArgs(pending, "
|
|
6091
|
+
requireNoExtraArgs(pending, "rig inspector stream [--once] [--seconds <n>] [--poll-ms <n>]");
|
|
5845
6092
|
const seconds = secondsResult.value ? parseRequiredPositiveInt(secondsResult.value, "--seconds") : null;
|
|
5846
6093
|
const pollMs = pollMsResult.value ? parseRequiredPositiveInt(pollMsResult.value, "--poll-ms") : null;
|
|
5847
6094
|
if (context.outputMode === "json" && !onceResult.value && !seconds) {
|
|
@@ -5935,7 +6182,7 @@ async function executeInspector(context, args) {
|
|
|
5935
6182
|
let pending = rest;
|
|
5936
6183
|
const scanIdResult = takeOption(pending, "--scan-id");
|
|
5937
6184
|
pending = scanIdResult.rest;
|
|
5938
|
-
requireNoExtraArgs(pending, "
|
|
6185
|
+
requireNoExtraArgs(pending, "rig inspector scan-upstream-drift [--scan-id <id>]");
|
|
5939
6186
|
const connection = await ensureLocalRigServerConnection2(context.projectRoot);
|
|
5940
6187
|
const response = await fetch(new URL("/api/inspector/tools/invoke", connection.baseUrl), {
|
|
5941
6188
|
method: "POST",
|
|
@@ -6046,7 +6293,7 @@ async function executeRemote(context, args) {
|
|
|
6046
6293
|
const [subcommand = "list", ...subRest] = rest;
|
|
6047
6294
|
switch (subcommand) {
|
|
6048
6295
|
case "list": {
|
|
6049
|
-
requireNoExtraArgs(subRest, "
|
|
6296
|
+
requireNoExtraArgs(subRest, "rig remote endpoint list");
|
|
6050
6297
|
const endpoints = listManagedRemoteEndpoints(undefined, context.projectRoot);
|
|
6051
6298
|
const redactedEndpoints = endpoints.map((endpoint2) => redactRemoteEndpoint(endpoint2));
|
|
6052
6299
|
if (context.outputMode === "text") {
|
|
@@ -6070,7 +6317,7 @@ async function executeRemote(context, args) {
|
|
|
6070
6317
|
pending2 = port.rest;
|
|
6071
6318
|
const token = takeOption(pending2, "--token");
|
|
6072
6319
|
pending2 = token.rest;
|
|
6073
|
-
requireNoExtraArgs(pending2, "
|
|
6320
|
+
requireNoExtraArgs(pending2, "rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
|
|
6074
6321
|
if (!alias.value || !host.value || !token.value || !port.value) {
|
|
6075
6322
|
throw new CliError2("remote endpoint add requires --alias, --host, --port, and --token.");
|
|
6076
6323
|
}
|
|
@@ -6097,7 +6344,7 @@ async function executeRemote(context, args) {
|
|
|
6097
6344
|
pending2 = port.rest;
|
|
6098
6345
|
const token = takeOption(pending2, "--token");
|
|
6099
6346
|
pending2 = token.rest;
|
|
6100
|
-
requireNoExtraArgs(pending2, "
|
|
6347
|
+
requireNoExtraArgs(pending2, "rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
|
|
6101
6348
|
if (!endpointId.value && !alias.value) {
|
|
6102
6349
|
throw new CliError2("remote endpoint update requires --id <id> or --alias <a>.");
|
|
6103
6350
|
}
|
|
@@ -6120,7 +6367,7 @@ async function executeRemote(context, args) {
|
|
|
6120
6367
|
let pending2 = subRest;
|
|
6121
6368
|
const alias = takeOption(pending2, "--alias");
|
|
6122
6369
|
pending2 = alias.rest;
|
|
6123
|
-
requireNoExtraArgs(pending2, "
|
|
6370
|
+
requireNoExtraArgs(pending2, "rig remote endpoint remove --alias <a>");
|
|
6124
6371
|
if (!alias.value) {
|
|
6125
6372
|
throw new CliError2("remote endpoint remove requires --alias.");
|
|
6126
6373
|
}
|
|
@@ -6137,7 +6384,7 @@ async function executeRemote(context, args) {
|
|
|
6137
6384
|
let pending2 = subRest;
|
|
6138
6385
|
const alias = takeOption(pending2, "--alias");
|
|
6139
6386
|
pending2 = alias.rest;
|
|
6140
|
-
requireNoExtraArgs(pending2, "
|
|
6387
|
+
requireNoExtraArgs(pending2, "rig remote endpoint test --alias <a>");
|
|
6141
6388
|
if (!alias.value) {
|
|
6142
6389
|
throw new CliError2("remote endpoint test requires --alias.");
|
|
6143
6390
|
}
|
|
@@ -6168,7 +6415,7 @@ async function executeRemote(context, args) {
|
|
|
6168
6415
|
}
|
|
6169
6416
|
}
|
|
6170
6417
|
case "migrate": {
|
|
6171
|
-
requireNoExtraArgs(subRest, "
|
|
6418
|
+
requireNoExtraArgs(subRest, "rig remote endpoint migrate");
|
|
6172
6419
|
const result = migrateManagedRemoteEndpoints(context.projectRoot);
|
|
6173
6420
|
if (context.outputMode === "text") {
|
|
6174
6421
|
console.log(`Imported ${result.imported} endpoint(s) from ${result.sourcePath}${result.skipped > 0 ? `, skipped ${result.skipped}` : ""}.`);
|
|
@@ -6176,7 +6423,7 @@ async function executeRemote(context, args) {
|
|
|
6176
6423
|
return { ok: true, group: "remote", command: "endpoint migrate", details: result };
|
|
6177
6424
|
}
|
|
6178
6425
|
case "doctor": {
|
|
6179
|
-
requireNoExtraArgs(subRest, "
|
|
6426
|
+
requireNoExtraArgs(subRest, "rig remote endpoint doctor");
|
|
6180
6427
|
const result = doctorManagedRemoteEndpoints(context.projectRoot);
|
|
6181
6428
|
if (context.outputMode === "text") {
|
|
6182
6429
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -6229,17 +6476,17 @@ async function executeRemote(context, args) {
|
|
|
6229
6476
|
try {
|
|
6230
6477
|
switch (command) {
|
|
6231
6478
|
case "test": {
|
|
6232
|
-
requireNoExtraArgs(pending, "
|
|
6479
|
+
requireNoExtraArgs(pending, "rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6233
6480
|
const response = await withClient((client) => client.ping());
|
|
6234
6481
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6235
6482
|
}
|
|
6236
6483
|
case "status": {
|
|
6237
|
-
requireNoExtraArgs(pending, "
|
|
6484
|
+
requireNoExtraArgs(pending, "rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6238
6485
|
const response = await withClient((client) => client.getState());
|
|
6239
6486
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6240
6487
|
}
|
|
6241
6488
|
case "tasks": {
|
|
6242
|
-
requireNoExtraArgs(pending, "
|
|
6489
|
+
requireNoExtraArgs(pending, "rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6243
6490
|
const response = await withClient((client) => client.getTasks());
|
|
6244
6491
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6245
6492
|
}
|
|
@@ -6249,7 +6496,7 @@ async function executeRemote(context, args) {
|
|
|
6249
6496
|
watchPending = secondsResult.rest;
|
|
6250
6497
|
const eventResult = takeOption(watchPending, "--event");
|
|
6251
6498
|
watchPending = eventResult.rest;
|
|
6252
|
-
requireNoExtraArgs(watchPending, "
|
|
6499
|
+
requireNoExtraArgs(watchPending, "rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6253
6500
|
const seconds = parseOptionalPositiveInt(secondsResult.value, "--seconds");
|
|
6254
6501
|
const eventFilter = eventResult.value || undefined;
|
|
6255
6502
|
if (context.outputMode === "json" && !seconds) {
|
|
@@ -6318,7 +6565,7 @@ async function executeRemote(context, args) {
|
|
|
6318
6565
|
case "stop":
|
|
6319
6566
|
case "continue":
|
|
6320
6567
|
case "refresh": {
|
|
6321
|
-
requireNoExtraArgs(pending, `
|
|
6568
|
+
requireNoExtraArgs(pending, `rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6322
6569
|
const response = await withClient(async (client) => {
|
|
6323
6570
|
switch (command) {
|
|
6324
6571
|
case "pause":
|
|
@@ -6341,7 +6588,7 @@ async function executeRemote(context, args) {
|
|
|
6341
6588
|
let countPending = pending;
|
|
6342
6589
|
const countResult = takeOption(countPending, "--count");
|
|
6343
6590
|
countPending = countResult.rest;
|
|
6344
|
-
requireNoExtraArgs(countPending, `
|
|
6591
|
+
requireNoExtraArgs(countPending, `rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6345
6592
|
const count = parseRequiredPositiveInt(countResult.value, "--count");
|
|
6346
6593
|
const response = await withClient(async (client) => command === "add-iterations" ? await client.addIterations(count) : await client.removeIterations(count));
|
|
6347
6594
|
assertRemoteOperationSuccess(command, response);
|
|
@@ -6352,8 +6599,8 @@ async function executeRemote(context, args) {
|
|
|
6352
6599
|
let taskPending = pending;
|
|
6353
6600
|
const taskResult = takeOption(taskPending, "--task");
|
|
6354
6601
|
taskPending = taskResult.rest;
|
|
6355
|
-
requireNoExtraArgs(taskPending, `
|
|
6356
|
-
const taskId = requireTask(taskResult.value, `
|
|
6602
|
+
requireNoExtraArgs(taskPending, `rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6603
|
+
const taskId = requireTask(taskResult.value, `rig remote ${command} --task <id>`);
|
|
6357
6604
|
const response = await withClient(async (client) => command === "prompt-preview" ? await client.getPromptPreview(taskId) : await client.getIterationOutput(taskId));
|
|
6358
6605
|
assertRemoteOperationSuccess(command, response);
|
|
6359
6606
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
@@ -6366,7 +6613,7 @@ async function executeRemote(context, args) {
|
|
|
6366
6613
|
orchestrationPending = maxIterationsResult.rest;
|
|
6367
6614
|
const directMergeResult = takeFlag(orchestrationPending, "--direct-merge");
|
|
6368
6615
|
orchestrationPending = directMergeResult.rest;
|
|
6369
|
-
requireNoExtraArgs(orchestrationPending, "
|
|
6616
|
+
requireNoExtraArgs(orchestrationPending, "rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
|
|
6370
6617
|
const response = await withClient((client) => client.startOrchestration({
|
|
6371
6618
|
maxWorkers: parseOptionalPositiveInt(maxWorkersResult.value, "--max-workers"),
|
|
6372
6619
|
maxIterations: parseOptionalPositiveInt(maxIterationsResult.value, "--max-iterations"),
|
|
@@ -6387,8 +6634,8 @@ async function executeRemote(context, args) {
|
|
|
6387
6634
|
let orchestrationPending = pending;
|
|
6388
6635
|
const idResult = takeOption(orchestrationPending, "--id");
|
|
6389
6636
|
orchestrationPending = idResult.rest;
|
|
6390
|
-
requireNoExtraArgs(orchestrationPending, `
|
|
6391
|
-
const orchestrationId = requireTask(idResult.value, `
|
|
6637
|
+
requireNoExtraArgs(orchestrationPending, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6638
|
+
const orchestrationId = requireTask(idResult.value, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6392
6639
|
const response = await withClient(async (client) => {
|
|
6393
6640
|
switch (command) {
|
|
6394
6641
|
case "orchestrate-pause":
|
|
@@ -6452,8 +6699,8 @@ var CANONICAL_STAGES = [
|
|
|
6452
6699
|
"Merge",
|
|
6453
6700
|
"Complete"
|
|
6454
6701
|
];
|
|
6455
|
-
function logDetail(
|
|
6456
|
-
return typeof
|
|
6702
|
+
function logDetail(log4) {
|
|
6703
|
+
return typeof log4.detail === "string" ? log4.detail.trim() : "";
|
|
6457
6704
|
}
|
|
6458
6705
|
function parseProviderProtocolLog(title, detail) {
|
|
6459
6706
|
if (title.trim().toLowerCase() !== "agent output")
|
|
@@ -6500,12 +6747,12 @@ function renderOperatorSnapshot(snapshot) {
|
|
|
6500
6747
|
const status = String(run.status ?? "unknown");
|
|
6501
6748
|
const logs = snapshot.logs ?? [];
|
|
6502
6749
|
const latestByStage = new Map;
|
|
6503
|
-
for (const
|
|
6504
|
-
const title = String(
|
|
6505
|
-
const stageName = String(
|
|
6750
|
+
for (const log4 of logs) {
|
|
6751
|
+
const title = String(log4.title ?? "").toLowerCase();
|
|
6752
|
+
const stageName = String(log4.stage ?? "").toLowerCase();
|
|
6506
6753
|
const stage = CANONICAL_STAGES.find((candidate) => candidate.toLowerCase() === title || candidate.toLowerCase() === stageName);
|
|
6507
6754
|
if (stage)
|
|
6508
|
-
latestByStage.set(stage,
|
|
6755
|
+
latestByStage.set(stage, log4);
|
|
6509
6756
|
}
|
|
6510
6757
|
const stageLines = CANONICAL_STAGES.flatMap((stage) => {
|
|
6511
6758
|
const match = latestByStage.get(stage);
|
|
@@ -7309,7 +7556,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
7309
7556
|
}
|
|
7310
7557
|
|
|
7311
7558
|
// packages/cli/src/commands/run.ts
|
|
7312
|
-
function
|
|
7559
|
+
function normalizeRemoteRunDetails2(payload) {
|
|
7313
7560
|
const run = payload.run;
|
|
7314
7561
|
if (!run || typeof run !== "object" || Array.isArray(run))
|
|
7315
7562
|
return null;
|
|
@@ -7321,11 +7568,11 @@ function normalizeRemoteRunDetails(payload) {
|
|
|
7321
7568
|
};
|
|
7322
7569
|
}
|
|
7323
7570
|
var REMOTE_TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged"]);
|
|
7324
|
-
function
|
|
7571
|
+
function isRemoteConnectionSelected2(projectRoot) {
|
|
7325
7572
|
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
7326
7573
|
}
|
|
7327
7574
|
async function listRunsForSelectedConnection(context, options = {}) {
|
|
7328
|
-
if (
|
|
7575
|
+
if (isRemoteConnectionSelected2(context.projectRoot)) {
|
|
7329
7576
|
return { runs: await listRunsViaServer(context, options), source: "server" };
|
|
7330
7577
|
}
|
|
7331
7578
|
return { runs: listAuthorityRuns3(context.projectRoot), source: "local" };
|
|
@@ -7334,9 +7581,6 @@ function runStringField(run, key, fallback = "") {
|
|
|
7334
7581
|
const value = run[key];
|
|
7335
7582
|
return typeof value === "string" && value.trim() ? value : fallback;
|
|
7336
7583
|
}
|
|
7337
|
-
function runDisplayTitle(run) {
|
|
7338
|
-
return runStringField(run, "title", runStringField(run, "taskId", "(untitled)"));
|
|
7339
|
-
}
|
|
7340
7584
|
function buildServerRunStatus(runs) {
|
|
7341
7585
|
const activeRuns = runs.filter((run) => !REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
7342
7586
|
const recentRuns = runs.filter((run) => REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
@@ -7406,10 +7650,10 @@ async function executeRun(context, args) {
|
|
|
7406
7650
|
const runtimeContext = loadRuntimeContextFromEnv2() ?? undefined;
|
|
7407
7651
|
switch (command) {
|
|
7408
7652
|
case "list": {
|
|
7409
|
-
requireNoExtraArgs(rest, "
|
|
7653
|
+
requireNoExtraArgs(rest, "rig run list");
|
|
7410
7654
|
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
7411
7655
|
if (context.outputMode === "text") {
|
|
7412
|
-
|
|
7656
|
+
printFormattedOutput(formatRunList(runs, { source }));
|
|
7413
7657
|
}
|
|
7414
7658
|
return { ok: true, group: "run", command, details: { runs, source } };
|
|
7415
7659
|
}
|
|
@@ -7419,7 +7663,7 @@ async function executeRun(context, args) {
|
|
|
7419
7663
|
pending = run.rest;
|
|
7420
7664
|
const purgeArtifacts = takeFlag(pending, "--purge-artifacts");
|
|
7421
7665
|
pending = purgeArtifacts.rest;
|
|
7422
|
-
requireNoExtraArgs(pending, "
|
|
7666
|
+
requireNoExtraArgs(pending, "rig run delete --run <id> [--purge-artifacts]");
|
|
7423
7667
|
if (!run.value) {
|
|
7424
7668
|
throw new CliError2("run delete requires --run <id>.");
|
|
7425
7669
|
}
|
|
@@ -7449,7 +7693,7 @@ async function executeRun(context, args) {
|
|
|
7449
7693
|
pending = keepRuntimes.rest;
|
|
7450
7694
|
const keepQueue = takeFlag(pending, "--keep-queue");
|
|
7451
7695
|
pending = keepQueue.rest;
|
|
7452
|
-
requireNoExtraArgs(pending, "
|
|
7696
|
+
requireNoExtraArgs(pending, "rig run cleanup --all [--keep-artifacts] [--keep-runtimes] [--keep-queue]");
|
|
7453
7697
|
if (!all.value) {
|
|
7454
7698
|
throw new CliError2("run cleanup currently requires --all.");
|
|
7455
7699
|
}
|
|
@@ -7468,20 +7712,25 @@ async function executeRun(context, args) {
|
|
|
7468
7712
|
}
|
|
7469
7713
|
case "show": {
|
|
7470
7714
|
let pending = rest;
|
|
7715
|
+
const rawResult = takeFlag(pending, "--raw");
|
|
7716
|
+
pending = rawResult.rest;
|
|
7471
7717
|
const run = takeOption(pending, "--run");
|
|
7472
7718
|
pending = run.rest;
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7719
|
+
const positionalRunId = pending.length > 0 && pending[0] && !pending[0].startsWith("-") ? pending[0] : undefined;
|
|
7720
|
+
const extra = positionalRunId ? pending.slice(1) : pending;
|
|
7721
|
+
requireNoExtraArgs(extra, "rig run show <id>|--run <id> [--raw]");
|
|
7722
|
+
const runId = run.value ?? positionalRunId;
|
|
7723
|
+
if (!runId) {
|
|
7724
|
+
throw new CliError2("run show requires a run id.");
|
|
7476
7725
|
}
|
|
7477
|
-
const record = readAuthorityRun4(context.projectRoot,
|
|
7726
|
+
const record = readAuthorityRun4(context.projectRoot, runId) ?? normalizeRemoteRunDetails2(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
7478
7727
|
if (!record) {
|
|
7479
|
-
throw new CliError2(`Run not found: ${
|
|
7728
|
+
throw new CliError2(`Run not found: ${runId}`, 2);
|
|
7480
7729
|
}
|
|
7481
7730
|
if (context.outputMode === "text") {
|
|
7482
|
-
|
|
7731
|
+
printFormattedOutput(rawResult.value ? JSON.stringify(record, null, 2) : formatRunCard(record));
|
|
7483
7732
|
}
|
|
7484
|
-
return { ok: true, group: "run", command, details: record };
|
|
7733
|
+
return { ok: true, group: "run", command, details: { ...record, rawOutput: rawResult.value } };
|
|
7485
7734
|
}
|
|
7486
7735
|
case "timeline": {
|
|
7487
7736
|
let pending = rest;
|
|
@@ -7489,7 +7738,7 @@ async function executeRun(context, args) {
|
|
|
7489
7738
|
pending = run.rest;
|
|
7490
7739
|
const follow = takeFlag(pending, "--follow");
|
|
7491
7740
|
pending = follow.rest;
|
|
7492
|
-
requireNoExtraArgs(pending, "
|
|
7741
|
+
requireNoExtraArgs(pending, "rig run timeline --run <id> [--follow]");
|
|
7493
7742
|
if (!run.value) {
|
|
7494
7743
|
throw new CliError2("run timeline requires --run <id>.");
|
|
7495
7744
|
}
|
|
@@ -7526,7 +7775,7 @@ async function executeRun(context, args) {
|
|
|
7526
7775
|
pending = pollMs.rest;
|
|
7527
7776
|
const positionalRunId = pending.length > 0 ? pending[0] : undefined;
|
|
7528
7777
|
const extra = positionalRunId ? pending.slice(1) : pending;
|
|
7529
|
-
requireNoExtraArgs(extra, "
|
|
7778
|
+
requireNoExtraArgs(extra, "rig run attach <run-id>|--run <run-id> [--message <text>] [--once|--follow] [--poll-ms <ms>]");
|
|
7530
7779
|
const runId = runOption.value ?? positionalRunId;
|
|
7531
7780
|
if (!runId) {
|
|
7532
7781
|
throw new CliError2("run attach requires a run id.", 2);
|
|
@@ -7546,28 +7795,18 @@ async function executeRun(context, args) {
|
|
|
7546
7795
|
return { ok: true, group: "run", command, details: { ...attached, steered: attached.steered || steered } };
|
|
7547
7796
|
}
|
|
7548
7797
|
case "status": {
|
|
7549
|
-
requireNoExtraArgs(rest, "
|
|
7798
|
+
requireNoExtraArgs(rest, "rig run status");
|
|
7550
7799
|
if (context.dryRun) {
|
|
7551
7800
|
if (context.outputMode === "text") {
|
|
7552
7801
|
console.log("[dry-run] rig run status");
|
|
7553
7802
|
}
|
|
7554
7803
|
return { ok: true, group: "run", command };
|
|
7555
7804
|
}
|
|
7556
|
-
const summary =
|
|
7805
|
+
const summary = isRemoteConnectionSelected2(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
7557
7806
|
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7558
7807
|
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7559
7808
|
if (context.outputMode === "text") {
|
|
7560
|
-
|
|
7561
|
-
for (const run of activeRuns) {
|
|
7562
|
-
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
7563
|
-
}
|
|
7564
|
-
if (recentRuns.length > 0) {
|
|
7565
|
-
console.log("");
|
|
7566
|
-
console.log("Recent runs:");
|
|
7567
|
-
for (const run of recentRuns) {
|
|
7568
|
-
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
7569
|
-
}
|
|
7570
|
-
}
|
|
7809
|
+
printFormattedOutput(formatRunStatus({ activeRuns, recentRuns, runs: Array.isArray(summary.runs) ? summary.runs : [...activeRuns, ...recentRuns] }, { source: isRemoteConnectionSelected2(context.projectRoot) ? "server" : "local" }));
|
|
7571
7810
|
}
|
|
7572
7811
|
return { ok: true, group: "run", command, details: summary };
|
|
7573
7812
|
}
|
|
@@ -7591,7 +7830,7 @@ async function executeRun(context, args) {
|
|
|
7591
7830
|
pending = pollResult.rest;
|
|
7592
7831
|
const noServerResult = takeFlag(pending, "--no-server");
|
|
7593
7832
|
pending = noServerResult.rest;
|
|
7594
|
-
requireNoExtraArgs(pending, "
|
|
7833
|
+
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]");
|
|
7595
7834
|
if (promptEpicResult.value && noEpicPromptResult.value) {
|
|
7596
7835
|
throw new CliError2("Cannot use --prompt-epic and --no-epic-prompt together.");
|
|
7597
7836
|
}
|
|
@@ -7639,7 +7878,7 @@ async function executeRun(context, args) {
|
|
|
7639
7878
|
};
|
|
7640
7879
|
}
|
|
7641
7880
|
case "resume": {
|
|
7642
|
-
requireNoExtraArgs(rest, "
|
|
7881
|
+
requireNoExtraArgs(rest, "rig run resume");
|
|
7643
7882
|
if (context.dryRun) {
|
|
7644
7883
|
if (context.outputMode === "text") {
|
|
7645
7884
|
console.log("[dry-run] rig run resume");
|
|
@@ -7653,7 +7892,7 @@ async function executeRun(context, args) {
|
|
|
7653
7892
|
return { ok: true, group: "run", command, details: resumed };
|
|
7654
7893
|
}
|
|
7655
7894
|
case "restart": {
|
|
7656
|
-
requireNoExtraArgs(rest, "
|
|
7895
|
+
requireNoExtraArgs(rest, "rig run restart");
|
|
7657
7896
|
if (context.dryRun) {
|
|
7658
7897
|
if (context.outputMode === "text") {
|
|
7659
7898
|
console.log("[dry-run] rig run restart");
|
|
@@ -7670,7 +7909,7 @@ async function executeRun(context, args) {
|
|
|
7670
7909
|
const runOption = takeOption(rest, "--run");
|
|
7671
7910
|
const positionalRunId = runOption.rest.length > 0 ? runOption.rest[0] : undefined;
|
|
7672
7911
|
const extra = positionalRunId ? runOption.rest.slice(1) : runOption.rest;
|
|
7673
|
-
requireNoExtraArgs(extra, "
|
|
7912
|
+
requireNoExtraArgs(extra, "rig run stop [<run-id>|--run <id>]");
|
|
7674
7913
|
const runId = runOption.value ?? positionalRunId;
|
|
7675
7914
|
if (context.dryRun) {
|
|
7676
7915
|
return {
|
|
@@ -7808,73 +8047,425 @@ async function executeServer(context, args, options) {
|
|
|
7808
8047
|
throw new CliError2(`Unknown server command: ${command}`);
|
|
7809
8048
|
}
|
|
7810
8049
|
}
|
|
7811
|
-
|
|
7812
|
-
// packages/cli/src/commands/task.ts
|
|
7813
|
-
import { readFileSync as readFileSync9 } from "fs";
|
|
7814
|
-
import { spawnSync as spawnSync3 } from "child_process";
|
|
7815
|
-
import { resolve as resolve19 } from "path";
|
|
7816
|
-
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
7817
|
-
import {
|
|
7818
|
-
taskArtifactDir,
|
|
7819
|
-
taskArtifacts,
|
|
7820
|
-
taskArtifactWrite,
|
|
7821
|
-
taskDeps,
|
|
7822
|
-
taskInfo,
|
|
7823
|
-
taskLookup as taskLookup2,
|
|
7824
|
-
taskReady,
|
|
7825
|
-
taskRecord,
|
|
7826
|
-
taskReopen,
|
|
7827
|
-
taskScope,
|
|
7828
|
-
taskStatus as taskStatus2,
|
|
7829
|
-
taskValidate,
|
|
7830
|
-
taskVerify
|
|
7831
|
-
} from "@rig/runtime/control-plane/native/task-ops";
|
|
7832
|
-
|
|
7833
|
-
// packages/cli/src/commands/_task-picker.ts
|
|
7834
|
-
import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
|
|
7835
|
-
function taskId2(task) {
|
|
7836
|
-
return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
|
|
8050
|
+
|
|
8051
|
+
// packages/cli/src/commands/task.ts
|
|
8052
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
8053
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
8054
|
+
import { resolve as resolve19 } from "path";
|
|
8055
|
+
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
8056
|
+
import {
|
|
8057
|
+
taskArtifactDir,
|
|
8058
|
+
taskArtifacts,
|
|
8059
|
+
taskArtifactWrite,
|
|
8060
|
+
taskDeps,
|
|
8061
|
+
taskInfo,
|
|
8062
|
+
taskLookup as taskLookup2,
|
|
8063
|
+
taskReady,
|
|
8064
|
+
taskRecord,
|
|
8065
|
+
taskReopen,
|
|
8066
|
+
taskScope,
|
|
8067
|
+
taskStatus as taskStatus2,
|
|
8068
|
+
taskValidate,
|
|
8069
|
+
taskVerify
|
|
8070
|
+
} from "@rig/runtime/control-plane/native/task-ops";
|
|
8071
|
+
|
|
8072
|
+
// packages/cli/src/commands/_task-picker.ts
|
|
8073
|
+
import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
|
|
8074
|
+
function taskId2(task) {
|
|
8075
|
+
return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
|
|
8076
|
+
}
|
|
8077
|
+
async function selectTaskWithTextPicker(tasks, io = {}) {
|
|
8078
|
+
if (tasks.length === 0)
|
|
8079
|
+
return null;
|
|
8080
|
+
if (tasks.length === 1)
|
|
8081
|
+
return tasks[0];
|
|
8082
|
+
const isTty = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
8083
|
+
if (!isTty) {
|
|
8084
|
+
throw new Error("task run requires an interactive terminal to pick a task; pass --task <id>, --next, or --detach with a task id.");
|
|
8085
|
+
}
|
|
8086
|
+
if (io.prompt || io.renderer) {
|
|
8087
|
+
const prompt = io.prompt ?? promptForTaskSelection;
|
|
8088
|
+
const renderer = io.renderer ?? { writeLine: (line) => process.stdout.write(`${line}
|
|
8089
|
+
`) };
|
|
8090
|
+
renderer.writeLine("Select Rig task:");
|
|
8091
|
+
for (const row of renderTaskPickerRows(tasks))
|
|
8092
|
+
renderer.writeLine(` ${row}`);
|
|
8093
|
+
const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
|
|
8094
|
+
if (!answer2)
|
|
8095
|
+
return null;
|
|
8096
|
+
if (/^\d+$/.test(answer2)) {
|
|
8097
|
+
const index2 = Number.parseInt(answer2, 10) - 1;
|
|
8098
|
+
return tasks[index2] ?? null;
|
|
8099
|
+
}
|
|
8100
|
+
return tasks.find((task) => taskId2(task) === answer2) ?? null;
|
|
8101
|
+
}
|
|
8102
|
+
const options = tasks.map((task, index2) => ({
|
|
8103
|
+
value: `${index2}`,
|
|
8104
|
+
label: `${taskId2(task)} \xB7 ${typeof task.title === "string" && task.title.trim() ? task.title.trim() : "Untitled task"}`,
|
|
8105
|
+
hint: typeof task.status === "string" && task.status.trim() ? task.status.trim() : undefined
|
|
8106
|
+
}));
|
|
8107
|
+
const answer = await select3({
|
|
8108
|
+
message: "Select Rig task",
|
|
8109
|
+
options
|
|
8110
|
+
});
|
|
8111
|
+
if (isCancel3(answer)) {
|
|
8112
|
+
cancel3("No task selected.");
|
|
8113
|
+
return null;
|
|
8114
|
+
}
|
|
8115
|
+
const index = Number.parseInt(String(answer), 10);
|
|
8116
|
+
return Number.isFinite(index) ? tasks[index] ?? null : null;
|
|
8117
|
+
}
|
|
8118
|
+
|
|
8119
|
+
// packages/cli/src/commands/_help-catalog.ts
|
|
8120
|
+
import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
|
|
8121
|
+
import pc4 from "picocolors";
|
|
8122
|
+
var TOP_LEVEL_SECTIONS = [
|
|
8123
|
+
{
|
|
8124
|
+
title: "Server",
|
|
8125
|
+
subtitle: "choose the local or remote Rig server that owns this repo",
|
|
8126
|
+
commands: [
|
|
8127
|
+
{ command: "rig server status", description: "Show the selected local/remote server for this repo." },
|
|
8128
|
+
{ command: "rig server use local", description: "Switch this repo back to the local Rig server." },
|
|
8129
|
+
{ command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
|
|
8130
|
+
{ command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
|
|
8131
|
+
{ command: "rig server list", description: "Show saved server aliases, including local." }
|
|
8132
|
+
]
|
|
8133
|
+
},
|
|
8134
|
+
{
|
|
8135
|
+
title: "Tasks",
|
|
8136
|
+
subtitle: "find work, inspect it, and submit Pi-backed workers",
|
|
8137
|
+
commands: [
|
|
8138
|
+
{ command: "rig task list", description: "List tasks from the selected task source/server." },
|
|
8139
|
+
{ command: "rig task next", description: "Show the next matching task as a selected-task card." },
|
|
8140
|
+
{ command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
|
|
8141
|
+
{ command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
|
|
8142
|
+
]
|
|
8143
|
+
},
|
|
8144
|
+
{
|
|
8145
|
+
title: "Runs",
|
|
8146
|
+
subtitle: "observe, attach to, and stop live or recent runs",
|
|
8147
|
+
commands: [
|
|
8148
|
+
{ command: "rig run list", description: "List recent runs from the selected server or local state." },
|
|
8149
|
+
{ command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
|
|
8150
|
+
{ command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
|
|
8151
|
+
{ command: "rig run stop <id>", description: "Request cancellation for a running worker." }
|
|
8152
|
+
]
|
|
8153
|
+
},
|
|
8154
|
+
{
|
|
8155
|
+
title: "Review / inbox",
|
|
8156
|
+
subtitle: "clear blocked runs and configure completion review",
|
|
8157
|
+
commands: [
|
|
8158
|
+
{ command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
|
|
8159
|
+
{ command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
|
|
8160
|
+
{ command: "rig review show|set", description: "Inspect or change the review gate policy." }
|
|
8161
|
+
]
|
|
8162
|
+
},
|
|
8163
|
+
{
|
|
8164
|
+
title: "Health / setup",
|
|
8165
|
+
subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
|
|
8166
|
+
commands: [
|
|
8167
|
+
{ command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
|
|
8168
|
+
{ command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
|
|
8169
|
+
{ command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
|
|
8170
|
+
]
|
|
8171
|
+
}
|
|
8172
|
+
];
|
|
8173
|
+
var PRIMARY_GROUPS = [
|
|
8174
|
+
{
|
|
8175
|
+
name: "server",
|
|
8176
|
+
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
8177
|
+
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
8178
|
+
commands: [
|
|
8179
|
+
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
8180
|
+
{ command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
|
|
8181
|
+
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
8182
|
+
{ command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
|
|
8183
|
+
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
8184
|
+
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
|
|
8185
|
+
],
|
|
8186
|
+
examples: [
|
|
8187
|
+
"rig server status",
|
|
8188
|
+
"rig server add prod https://where.rig-does.work",
|
|
8189
|
+
"rig server use prod",
|
|
8190
|
+
"rig server use local",
|
|
8191
|
+
"rig server start --port 3773"
|
|
8192
|
+
],
|
|
8193
|
+
next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
|
|
8194
|
+
advanced: ["Compatibility alias: `rig connect ...` remains callable."]
|
|
8195
|
+
},
|
|
8196
|
+
{
|
|
8197
|
+
name: "task",
|
|
8198
|
+
summary: "Find work, start Pi-backed runs, and validate task results.",
|
|
8199
|
+
usage: ["rig task <list|next|show|run> [options]"],
|
|
8200
|
+
commands: [
|
|
8201
|
+
{ command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
|
|
8202
|
+
{ command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
|
|
8203
|
+
{ command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
|
|
8204
|
+
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
8205
|
+
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
8206
|
+
{ command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
|
|
8207
|
+
{ command: "report-bug", description: "Create a structured bug report/task." }
|
|
8208
|
+
],
|
|
8209
|
+
examples: [
|
|
8210
|
+
"rig task list --assignee @me --limit 20",
|
|
8211
|
+
"rig task next",
|
|
8212
|
+
"rig task show 123 --raw",
|
|
8213
|
+
"rig task run --next",
|
|
8214
|
+
"rig task run #123 --runtime-adapter pi",
|
|
8215
|
+
"rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
|
|
8216
|
+
],
|
|
8217
|
+
next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
|
|
8218
|
+
},
|
|
8219
|
+
{
|
|
8220
|
+
name: "run",
|
|
8221
|
+
summary: "Observe, attach to, and control Rig runs.",
|
|
8222
|
+
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
8223
|
+
commands: [
|
|
8224
|
+
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
8225
|
+
{ command: "status", description: "Render active and recent run groups.", primary: true },
|
|
8226
|
+
{ command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
|
|
8227
|
+
{ command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; --follow launches native bundled Pi for live Pi runs.", primary: true },
|
|
8228
|
+
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
8229
|
+
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
8230
|
+
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
8231
|
+
],
|
|
8232
|
+
examples: [
|
|
8233
|
+
"rig run list",
|
|
8234
|
+
"rig run status",
|
|
8235
|
+
"rig run show <run-id>",
|
|
8236
|
+
"rig run attach <run-id> --follow",
|
|
8237
|
+
"rig run stop <run-id>"
|
|
8238
|
+
],
|
|
8239
|
+
next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
|
|
8240
|
+
},
|
|
8241
|
+
{
|
|
8242
|
+
name: "inbox",
|
|
8243
|
+
summary: "Review approval and user-input requests that block worker runs.",
|
|
8244
|
+
usage: ["rig inbox <approvals|approve|inputs|respond> [options]"],
|
|
8245
|
+
commands: [
|
|
8246
|
+
{ command: "approvals [--run <id>] [--task <id>]", description: "List pending approvals.", primary: true },
|
|
8247
|
+
{ command: "inputs [--run <id>] [--task <id>]", description: "List pending user-input requests.", primary: true },
|
|
8248
|
+
{ command: "approve --run <id> --request <id> --decision approve|reject", description: "Resolve an approval request." },
|
|
8249
|
+
{ command: "respond --run <id> --request <id> --answer key=value", description: "Answer a user-input request." }
|
|
8250
|
+
],
|
|
8251
|
+
examples: [
|
|
8252
|
+
"rig inbox approvals",
|
|
8253
|
+
"rig inbox inputs --run <run-id>",
|
|
8254
|
+
"rig inbox approve --run <run-id> --request <request-id> --decision approve"
|
|
8255
|
+
],
|
|
8256
|
+
next: ["Rejoin the run after resolving a block: `rig run attach <run-id> --follow`."]
|
|
8257
|
+
},
|
|
8258
|
+
{
|
|
8259
|
+
name: "review",
|
|
8260
|
+
summary: "Inspect or change completion review gate policy.",
|
|
8261
|
+
usage: ["rig review <show|set>"],
|
|
8262
|
+
commands: [
|
|
8263
|
+
{ command: "show", description: "Show current review gate settings.", primary: true },
|
|
8264
|
+
{ command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider.", primary: true }
|
|
8265
|
+
],
|
|
8266
|
+
examples: ["rig review show", "rig review set required --provider greptile"],
|
|
8267
|
+
next: ["Use `rig inbox approvals` for blocked run handoffs."]
|
|
8268
|
+
},
|
|
8269
|
+
{
|
|
8270
|
+
name: "init",
|
|
8271
|
+
summary: "Set up Rig for this repo: server, GitHub auth, checkout strategy, task source, and Pi wiring.",
|
|
8272
|
+
usage: ["rig init [--yes] [--server local|remote] [--repo owner/repo] [--remote-url <url>]"],
|
|
8273
|
+
commands: [
|
|
8274
|
+
{ command: "init", description: "Interactive setup wizard for a new or existing Rig repo.", primary: true },
|
|
8275
|
+
{ command: "init --yes", description: "Non-interactive setup using detected/default settings.", primary: true },
|
|
8276
|
+
{ command: "init --server remote --remote-url <url>", description: "Link this repo to a remote Rig server.", primary: true },
|
|
8277
|
+
{ command: "init --repair", description: "Repair missing private state without replacing project config." }
|
|
8278
|
+
],
|
|
8279
|
+
examples: [
|
|
8280
|
+
"rig init",
|
|
8281
|
+
"rig init --yes --repo humanity-org/humanwork",
|
|
8282
|
+
"rig init --server remote --remote-url https://where.rig-does.work --repo owner/repo"
|
|
8283
|
+
],
|
|
8284
|
+
next: ["After init, run `rig server status`.", "Then use `rig task list` and `rig task run --next` for day-to-day work."]
|
|
8285
|
+
},
|
|
8286
|
+
{
|
|
8287
|
+
name: "doctor",
|
|
8288
|
+
summary: "Diagnostics for project/server/GitHub/Pi state.",
|
|
8289
|
+
usage: ["rig doctor"],
|
|
8290
|
+
commands: [
|
|
8291
|
+
{ command: "doctor", description: "Run setup and runtime diagnostics.", primary: true },
|
|
8292
|
+
{ command: "check", description: "Compatibility spelling for diagnostics." }
|
|
8293
|
+
],
|
|
8294
|
+
examples: ["rig doctor", "rig doctor --json"],
|
|
8295
|
+
next: ["Use `rig server status` and `rig github auth status` to inspect common failure points."]
|
|
8296
|
+
},
|
|
8297
|
+
{
|
|
8298
|
+
name: "github",
|
|
8299
|
+
summary: "GitHub auth helpers for the selected Rig server.",
|
|
8300
|
+
usage: ["rig github auth <status|import-gh|token>"],
|
|
8301
|
+
commands: [
|
|
8302
|
+
{ command: "auth status", description: "Show GitHub auth state.", primary: true },
|
|
8303
|
+
{ command: "auth import-gh", description: "Import the current `gh` token into the selected server." },
|
|
8304
|
+
{ command: "auth token --token <token>", description: "Store a token on the selected server." }
|
|
8305
|
+
],
|
|
8306
|
+
examples: ["rig github auth status", "rig github auth import-gh"],
|
|
8307
|
+
next: ["After auth is valid, use `rig task run --next`."]
|
|
8308
|
+
}
|
|
8309
|
+
];
|
|
8310
|
+
var ADVANCED_GROUPS = [
|
|
8311
|
+
{ 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." }] },
|
|
8312
|
+
{ name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
|
|
8313
|
+
{ 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." }] },
|
|
8314
|
+
{ name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
|
|
8315
|
+
{ name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
|
|
8316
|
+
{ name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
|
|
8317
|
+
{ name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
|
|
8318
|
+
{ name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
|
|
8319
|
+
{ name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
|
|
8320
|
+
{ name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
|
|
8321
|
+
{ name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
|
|
8322
|
+
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
8323
|
+
{ name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
|
|
8324
|
+
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
8325
|
+
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
8326
|
+
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
8327
|
+
];
|
|
8328
|
+
var ADVANCED_COMMANDS = [
|
|
8329
|
+
{ command: "rig server task-run ...", description: "Internal server-owned task execution entry point." },
|
|
8330
|
+
{ command: "rig server notify-test [--event <type>]", description: "Internal event notification smoke command." },
|
|
8331
|
+
{ command: "rig run start|start-serial|start-parallel", description: "Compatibility local run starters; prefer `rig task run ...`." },
|
|
8332
|
+
{ command: "rig setup install-agent-shell", description: "Development helper for materializing the agent shell." },
|
|
8333
|
+
{ command: "rig remote orchestrate-*", description: "Compatibility remote orchestration commands." }
|
|
8334
|
+
];
|
|
8335
|
+
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
8336
|
+
function heading(title) {
|
|
8337
|
+
return pc4.bold(pc4.cyan(title));
|
|
8338
|
+
}
|
|
8339
|
+
function commandLine(command, description) {
|
|
8340
|
+
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
8341
|
+
return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
|
|
8342
|
+
}
|
|
8343
|
+
function renderCommandBlock(commands) {
|
|
8344
|
+
return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8345
|
+
`);
|
|
8346
|
+
}
|
|
8347
|
+
function renderGroup(group) {
|
|
8348
|
+
const lines = [
|
|
8349
|
+
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
8350
|
+
"",
|
|
8351
|
+
pc4.bold("Usage"),
|
|
8352
|
+
...group.usage.map((line) => ` ${line}`),
|
|
8353
|
+
"",
|
|
8354
|
+
pc4.bold("Commands"),
|
|
8355
|
+
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
8356
|
+
];
|
|
8357
|
+
if (group.examples?.length) {
|
|
8358
|
+
lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
|
|
8359
|
+
}
|
|
8360
|
+
if (group.next?.length) {
|
|
8361
|
+
lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
8362
|
+
}
|
|
8363
|
+
if (group.advanced?.length) {
|
|
8364
|
+
lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
8365
|
+
}
|
|
8366
|
+
return lines.join(`
|
|
8367
|
+
`);
|
|
8368
|
+
}
|
|
8369
|
+
function renderTopLevelHelp() {
|
|
8370
|
+
return [
|
|
8371
|
+
`${heading("rig")} ${pc4.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
8372
|
+
pc4.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox/review gates."),
|
|
8373
|
+
"",
|
|
8374
|
+
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
8375
|
+
`${pc4.bold(pc4.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc4.dim(section.subtitle)}`,
|
|
8376
|
+
renderCommandBlock(section.commands),
|
|
8377
|
+
""
|
|
8378
|
+
]),
|
|
8379
|
+
pc4.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
|
|
8380
|
+
"",
|
|
8381
|
+
pc4.bold("Global options"),
|
|
8382
|
+
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8383
|
+
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8384
|
+
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
8385
|
+
].join(`
|
|
8386
|
+
`).trimEnd();
|
|
7837
8387
|
}
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
8388
|
+
function renderAdvancedHelp() {
|
|
8389
|
+
return [
|
|
8390
|
+
`${heading("rig advanced")} \u2014 compatibility, diagnostics, and internal surfaces`,
|
|
8391
|
+
"",
|
|
8392
|
+
pc4.bold("Primary groups"),
|
|
8393
|
+
" server, task, run, inbox, review, init, doctor, github",
|
|
8394
|
+
"",
|
|
8395
|
+
pc4.bold("Advanced commands"),
|
|
8396
|
+
...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
|
|
8397
|
+
"",
|
|
8398
|
+
pc4.bold("Advanced groups"),
|
|
8399
|
+
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
8400
|
+
"",
|
|
8401
|
+
pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, `rig run`, `rig inbox`, and `rig review` for day-to-day work.")
|
|
8402
|
+
].join(`
|
|
8403
|
+
`);
|
|
8404
|
+
}
|
|
8405
|
+
function renderGroupHelp(groupName) {
|
|
8406
|
+
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
8407
|
+
return group ? renderGroup(group) : null;
|
|
8408
|
+
}
|
|
8409
|
+
function shouldUseClackOutput2() {
|
|
8410
|
+
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
8411
|
+
}
|
|
8412
|
+
function printTopLevelHelp() {
|
|
8413
|
+
if (!shouldUseClackOutput2()) {
|
|
8414
|
+
console.log(renderTopLevelHelp());
|
|
8415
|
+
return;
|
|
7846
8416
|
}
|
|
7847
|
-
|
|
7848
|
-
|
|
7849
|
-
|
|
7850
|
-
`) };
|
|
7851
|
-
renderer.writeLine("Select Rig task:");
|
|
7852
|
-
for (const row of renderTaskPickerRows(tasks))
|
|
7853
|
-
renderer.writeLine(` ${row}`);
|
|
7854
|
-
const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
|
|
7855
|
-
if (!answer2)
|
|
7856
|
-
return null;
|
|
7857
|
-
if (/^\d+$/.test(answer2)) {
|
|
7858
|
-
const index2 = Number.parseInt(answer2, 10) - 1;
|
|
7859
|
-
return tasks[index2] ?? null;
|
|
7860
|
-
}
|
|
7861
|
-
return tasks.find((task) => taskId2(task) === answer2) ?? null;
|
|
8417
|
+
intro3("rig");
|
|
8418
|
+
for (const section of TOP_LEVEL_SECTIONS) {
|
|
8419
|
+
note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
|
|
7862
8420
|
}
|
|
7863
|
-
|
|
7864
|
-
|
|
7865
|
-
|
|
7866
|
-
|
|
7867
|
-
|
|
7868
|
-
|
|
7869
|
-
|
|
7870
|
-
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
7874
|
-
|
|
8421
|
+
log4.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
|
|
8422
|
+
note4([
|
|
8423
|
+
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8424
|
+
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8425
|
+
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
8426
|
+
].join(`
|
|
8427
|
+
`), "Global options");
|
|
8428
|
+
outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
|
|
8429
|
+
}
|
|
8430
|
+
function printAdvancedHelp() {
|
|
8431
|
+
if (!shouldUseClackOutput2()) {
|
|
8432
|
+
console.log(renderAdvancedHelp());
|
|
8433
|
+
return;
|
|
7875
8434
|
}
|
|
7876
|
-
|
|
7877
|
-
|
|
8435
|
+
intro3("rig advanced");
|
|
8436
|
+
note4(ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8437
|
+
`), "Advanced commands");
|
|
8438
|
+
note4(ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)).join(`
|
|
8439
|
+
`), "Advanced groups");
|
|
8440
|
+
outro3("Primary daily flow: rig server \xB7 rig task \xB7 rig run \xB7 rig inbox \xB7 rig review.");
|
|
8441
|
+
}
|
|
8442
|
+
function printGroupHelpDocument(groupName) {
|
|
8443
|
+
const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
|
|
8444
|
+
if (!shouldUseClackOutput2()) {
|
|
8445
|
+
console.log(rendered);
|
|
8446
|
+
return;
|
|
8447
|
+
}
|
|
8448
|
+
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
8449
|
+
if (!group) {
|
|
8450
|
+
printTopLevelHelp();
|
|
8451
|
+
return;
|
|
8452
|
+
}
|
|
8453
|
+
intro3(`rig ${group.name}`);
|
|
8454
|
+
note4(group.summary, "Purpose");
|
|
8455
|
+
note4(group.usage.join(`
|
|
8456
|
+
`), "Usage");
|
|
8457
|
+
note4(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8458
|
+
`), "Commands");
|
|
8459
|
+
if (group.examples?.length)
|
|
8460
|
+
note4(group.examples.map((line) => `$ ${line}`).join(`
|
|
8461
|
+
`), "Examples");
|
|
8462
|
+
if (group.next?.length)
|
|
8463
|
+
note4(group.next.map((line) => `\u203A ${line}`).join(`
|
|
8464
|
+
`), "Next steps");
|
|
8465
|
+
if (group.advanced?.length)
|
|
8466
|
+
log4.info(group.advanced.join(`
|
|
8467
|
+
`));
|
|
8468
|
+
outro3("Run with --json when scripts need structured output.");
|
|
7878
8469
|
}
|
|
7879
8470
|
|
|
7880
8471
|
// packages/cli/src/commands/task.ts
|
|
@@ -8028,27 +8619,30 @@ function summarizeTask(task, options = {}) {
|
|
|
8028
8619
|
...options.raw ? { raw: raw ?? task } : {}
|
|
8029
8620
|
};
|
|
8030
8621
|
}
|
|
8031
|
-
function printTaskSummary(task) {
|
|
8032
|
-
console.log(formatTaskList([task]));
|
|
8033
|
-
}
|
|
8034
8622
|
async function validatorRegistryForTaskCommands(projectRoot) {
|
|
8035
8623
|
return buildPluginHostContext(projectRoot).then((ctx) => ctx?.validatorRegistry ?? undefined).catch(() => {
|
|
8036
8624
|
return;
|
|
8037
8625
|
});
|
|
8038
8626
|
}
|
|
8039
8627
|
async function executeTask(context, args, options) {
|
|
8040
|
-
|
|
8628
|
+
if (args.length === 0) {
|
|
8629
|
+
if (context.outputMode === "text") {
|
|
8630
|
+
printGroupHelpDocument("task");
|
|
8631
|
+
}
|
|
8632
|
+
return { ok: true, group: "task", command: "help" };
|
|
8633
|
+
}
|
|
8634
|
+
const [command = "help", ...rest] = args;
|
|
8041
8635
|
switch (command) {
|
|
8042
8636
|
case "list": {
|
|
8043
8637
|
let pending = rest;
|
|
8044
8638
|
const rawResult = takeFlag(pending, "--raw");
|
|
8045
8639
|
pending = rawResult.rest;
|
|
8046
8640
|
const { filters, rest: remaining } = parseTaskFilters(pending);
|
|
8047
|
-
requireNoExtraArgs(remaining, "
|
|
8641
|
+
requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
8048
8642
|
const tasks = await listWorkspaceTasksViaServer(context, filters);
|
|
8049
8643
|
if (context.outputMode === "text") {
|
|
8050
8644
|
const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
|
|
8051
|
-
|
|
8645
|
+
printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
|
|
8052
8646
|
}
|
|
8053
8647
|
return {
|
|
8054
8648
|
ok: true,
|
|
@@ -8058,10 +8652,13 @@ async function executeTask(context, args, options) {
|
|
|
8058
8652
|
};
|
|
8059
8653
|
}
|
|
8060
8654
|
case "show": {
|
|
8061
|
-
|
|
8655
|
+
let pending = rest;
|
|
8656
|
+
const rawResult = takeFlag(pending, "--raw");
|
|
8657
|
+
pending = rawResult.rest;
|
|
8658
|
+
const taskOption = takeOption(pending, "--task");
|
|
8062
8659
|
const positional = taskOption.rest.length > 0 && taskOption.rest[0] && !taskOption.rest[0].startsWith("-") ? taskOption.rest[0] : undefined;
|
|
8063
8660
|
const remaining = positional ? taskOption.rest.slice(1) : taskOption.rest;
|
|
8064
|
-
requireNoExtraArgs(remaining, "
|
|
8661
|
+
requireNoExtraArgs(remaining, "rig task show <id>|--task <id> [--raw]");
|
|
8065
8662
|
const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
|
|
8066
8663
|
if (!taskId3)
|
|
8067
8664
|
throw new CliError2("task show requires a task id.", 2);
|
|
@@ -8069,19 +8666,20 @@ async function executeTask(context, args, options) {
|
|
|
8069
8666
|
if (!task)
|
|
8070
8667
|
throw new CliError2(`Task not found: ${taskId3}`, 3);
|
|
8071
8668
|
const summary = summarizeTask(task, { raw: true });
|
|
8072
|
-
if (context.outputMode === "text")
|
|
8073
|
-
|
|
8074
|
-
|
|
8669
|
+
if (context.outputMode === "text") {
|
|
8670
|
+
printFormattedOutput(rawResult.value ? JSON.stringify(summary, null, 2) : formatTaskDetails(summary));
|
|
8671
|
+
}
|
|
8672
|
+
return { ok: true, group: "task", command, details: { task: summary, raw: rawResult.value } };
|
|
8075
8673
|
}
|
|
8076
8674
|
case "next": {
|
|
8077
8675
|
const { filters, rest: remaining } = parseTaskFilters(rest);
|
|
8078
|
-
requireNoExtraArgs(remaining, "
|
|
8676
|
+
requireNoExtraArgs(remaining, "rig task next [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
8079
8677
|
const selected = await selectNextWorkspaceTaskViaServer(context, filters);
|
|
8080
8678
|
if (context.outputMode === "text") {
|
|
8081
8679
|
if (selected.task) {
|
|
8082
|
-
|
|
8680
|
+
printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
|
|
8083
8681
|
} else {
|
|
8084
|
-
|
|
8682
|
+
printFormattedOutput("No matching tasks.\n\nNext\n\u203A Try `rig task list` to inspect available work.\n\u203A Check server: `rig server status`");
|
|
8085
8683
|
}
|
|
8086
8684
|
}
|
|
8087
8685
|
return {
|
|
@@ -8097,31 +8695,31 @@ async function executeTask(context, args, options) {
|
|
|
8097
8695
|
}
|
|
8098
8696
|
case "info": {
|
|
8099
8697
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8100
|
-
requireNoExtraArgs(remaining, "
|
|
8698
|
+
requireNoExtraArgs(remaining, "rig task info [--task <task-id>]");
|
|
8101
8699
|
await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, task || undefined));
|
|
8102
8700
|
return { ok: true, group: "task", command, details: { task: task || null } };
|
|
8103
8701
|
}
|
|
8104
8702
|
case "scope": {
|
|
8105
8703
|
const filesFlag = takeFlag(rest, "--files");
|
|
8106
8704
|
const { value: task, rest: remaining } = takeOption(filesFlag.rest, "--task");
|
|
8107
|
-
requireNoExtraArgs(remaining, "
|
|
8705
|
+
requireNoExtraArgs(remaining, "rig task scope [--task <id>] [--files]");
|
|
8108
8706
|
await withMutedConsole(context.outputMode === "json", () => taskScope(context.projectRoot, filesFlag.value, task || undefined));
|
|
8109
8707
|
return { ok: true, group: "task", command, details: { files: filesFlag.value, task: task || null } };
|
|
8110
8708
|
}
|
|
8111
8709
|
case "deps":
|
|
8112
|
-
requireNoExtraArgs(rest, "
|
|
8710
|
+
requireNoExtraArgs(rest, "rig task deps");
|
|
8113
8711
|
await withMutedConsole(context.outputMode === "json", () => taskDeps(context.projectRoot));
|
|
8114
8712
|
return { ok: true, group: "task", command };
|
|
8115
8713
|
case "status":
|
|
8116
|
-
requireNoExtraArgs(rest, "
|
|
8714
|
+
requireNoExtraArgs(rest, "rig task status");
|
|
8117
8715
|
withMutedConsole(context.outputMode === "json", () => taskStatus2(context.projectRoot));
|
|
8118
8716
|
return { ok: true, group: "task", command };
|
|
8119
8717
|
case "artifacts":
|
|
8120
|
-
requireNoExtraArgs(rest, "
|
|
8718
|
+
requireNoExtraArgs(rest, "rig task artifacts");
|
|
8121
8719
|
withMutedConsole(context.outputMode === "json", () => taskArtifacts(context.projectRoot));
|
|
8122
8720
|
return { ok: true, group: "task", command };
|
|
8123
8721
|
case "artifact-dir": {
|
|
8124
|
-
requireNoExtraArgs(rest, "
|
|
8722
|
+
requireNoExtraArgs(rest, "rig task artifact-dir");
|
|
8125
8723
|
const path = taskArtifactDir(context.projectRoot);
|
|
8126
8724
|
if (context.outputMode === "text") {
|
|
8127
8725
|
console.log(path);
|
|
@@ -8130,7 +8728,7 @@ async function executeTask(context, args, options) {
|
|
|
8130
8728
|
}
|
|
8131
8729
|
case "artifact-write": {
|
|
8132
8730
|
if (rest.length < 1) {
|
|
8133
|
-
throw new CliError2(`Usage:
|
|
8731
|
+
throw new CliError2(`Usage: rig task artifact-write <filename> [--file <path>]
|
|
8134
8732
|
` + ` Reads content from stdin (or --file), writes to the active task artifact dir.
|
|
8135
8733
|
` + " Example: echo '...' | rig task artifact-write collection-audit.md");
|
|
8136
8734
|
}
|
|
@@ -8143,7 +8741,7 @@ async function executeTask(context, args, options) {
|
|
|
8143
8741
|
content = await readStdin();
|
|
8144
8742
|
}
|
|
8145
8743
|
if (!artifactFilename) {
|
|
8146
|
-
throw new CliError2("Usage:
|
|
8744
|
+
throw new CliError2("Usage: rig task artifact-write <filename> [--file path]");
|
|
8147
8745
|
}
|
|
8148
8746
|
withMutedConsole(context.outputMode === "json", () => taskArtifactWrite(context.projectRoot, artifactFilename, content));
|
|
8149
8747
|
return { ok: true, group: "task", command, details: { filename: artifactFilename } };
|
|
@@ -8152,11 +8750,11 @@ async function executeTask(context, args, options) {
|
|
|
8152
8750
|
return options.executeTaskReportBug(context, rest);
|
|
8153
8751
|
case "lookup": {
|
|
8154
8752
|
if (rest.length !== 1) {
|
|
8155
|
-
throw new CliError2("Usage:
|
|
8753
|
+
throw new CliError2("Usage: rig task lookup <task-id>");
|
|
8156
8754
|
}
|
|
8157
8755
|
const lookupId = rest[0];
|
|
8158
8756
|
if (!lookupId) {
|
|
8159
|
-
throw new CliError2("Usage:
|
|
8757
|
+
throw new CliError2("Usage: rig task lookup <task-id>");
|
|
8160
8758
|
}
|
|
8161
8759
|
const result = taskLookup2(context.projectRoot, lookupId);
|
|
8162
8760
|
if (context.outputMode === "text") {
|
|
@@ -8166,17 +8764,17 @@ async function executeTask(context, args, options) {
|
|
|
8166
8764
|
}
|
|
8167
8765
|
case "record": {
|
|
8168
8766
|
if (rest.length < 2) {
|
|
8169
|
-
throw new CliError2("Usage:
|
|
8767
|
+
throw new CliError2("Usage: rig task record <decision|failure> <text>");
|
|
8170
8768
|
}
|
|
8171
8769
|
const type = rest[0];
|
|
8172
8770
|
if (type !== "decision" && type !== "failure") {
|
|
8173
|
-
throw new CliError2("Usage:
|
|
8771
|
+
throw new CliError2("Usage: rig task record <decision|failure> <text>");
|
|
8174
8772
|
}
|
|
8175
8773
|
withMutedConsole(context.outputMode === "json", () => taskRecord(context.projectRoot, type, rest.slice(1).join(" ")));
|
|
8176
8774
|
return { ok: true, group: "task", command, details: { type: rest[0] } };
|
|
8177
8775
|
}
|
|
8178
8776
|
case "ready":
|
|
8179
|
-
requireNoExtraArgs(rest, "
|
|
8777
|
+
requireNoExtraArgs(rest, "rig task ready");
|
|
8180
8778
|
await withMutedConsole(context.outputMode === "json", () => taskReady(context.projectRoot));
|
|
8181
8779
|
return { ok: true, group: "task", command };
|
|
8182
8780
|
case "run": {
|
|
@@ -8213,7 +8811,7 @@ async function executeTask(context, args, options) {
|
|
|
8213
8811
|
if (positionalTaskId) {
|
|
8214
8812
|
pending = pending.slice(1);
|
|
8215
8813
|
}
|
|
8216
|
-
requireNoExtraArgs(pending, "
|
|
8814
|
+
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]");
|
|
8217
8815
|
if (nextResult.value && (taskResult.value || positionalTaskId)) {
|
|
8218
8816
|
throw new CliError2("task run cannot combine --next with an explicit task id.", 2);
|
|
8219
8817
|
}
|
|
@@ -8267,10 +8865,24 @@ async function executeTask(context, args, options) {
|
|
|
8267
8865
|
});
|
|
8268
8866
|
let attachDetails = null;
|
|
8269
8867
|
if (!detachResult.value && context.outputMode === "text") {
|
|
8270
|
-
|
|
8868
|
+
printFormattedOutput(formatSubmittedRun({
|
|
8869
|
+
runId: submitted.runId,
|
|
8870
|
+
task: selectedTask ? summarizeTask(selectedTask) : null,
|
|
8871
|
+
runtimeAdapter,
|
|
8872
|
+
runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
|
|
8873
|
+
interactionMode: interactionModeResult.value || "default",
|
|
8874
|
+
detached: false
|
|
8875
|
+
}));
|
|
8271
8876
|
attachDetails = await attachRunOperatorView(context, { runId: submitted.runId, follow: true });
|
|
8272
8877
|
} else if (context.outputMode === "text") {
|
|
8273
|
-
|
|
8878
|
+
printFormattedOutput(formatSubmittedRun({
|
|
8879
|
+
runId: submitted.runId,
|
|
8880
|
+
task: selectedTask ? summarizeTask(selectedTask) : null,
|
|
8881
|
+
runtimeAdapter,
|
|
8882
|
+
runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
|
|
8883
|
+
interactionMode: interactionModeResult.value || "default",
|
|
8884
|
+
detached: true
|
|
8885
|
+
}));
|
|
8274
8886
|
}
|
|
8275
8887
|
return {
|
|
8276
8888
|
ok: true,
|
|
@@ -8294,7 +8906,7 @@ async function executeTask(context, args, options) {
|
|
|
8294
8906
|
}
|
|
8295
8907
|
case "validate": {
|
|
8296
8908
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8297
|
-
requireNoExtraArgs(remaining, "
|
|
8909
|
+
requireNoExtraArgs(remaining, "rig task validate [--task <task-id>]");
|
|
8298
8910
|
if (context.dryRun) {
|
|
8299
8911
|
await context.runCommand(["rig", "task", "validate", ...task ? ["--task", task] : []]);
|
|
8300
8912
|
return { ok: true, group: "task", command, details: { task: task || "active" } };
|
|
@@ -8307,7 +8919,7 @@ async function executeTask(context, args, options) {
|
|
|
8307
8919
|
}
|
|
8308
8920
|
case "verify": {
|
|
8309
8921
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8310
|
-
requireNoExtraArgs(remaining, "
|
|
8922
|
+
requireNoExtraArgs(remaining, "rig task verify [--task <task-id>]");
|
|
8311
8923
|
if (context.dryRun) {
|
|
8312
8924
|
await context.runCommand(["rig", "task", "verify", ...task ? ["--task", task] : []]);
|
|
8313
8925
|
return { ok: true, group: "task", command, details: { task: task || "active" } };
|
|
@@ -8320,15 +8932,15 @@ async function executeTask(context, args, options) {
|
|
|
8320
8932
|
}
|
|
8321
8933
|
case "reset": {
|
|
8322
8934
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8323
|
-
requireNoExtraArgs(remaining, "
|
|
8324
|
-
const requiredTask = requireTask(task, "
|
|
8935
|
+
requireNoExtraArgs(remaining, "rig task reset --task <task-id>");
|
|
8936
|
+
const requiredTask = requireTask(task, "rig task reset --task <task-id>");
|
|
8325
8937
|
await context.runCommand(["br", "--no-db", "update", requiredTask, "--status", "open"]);
|
|
8326
8938
|
return { ok: true, group: "task", command, details: { task: requiredTask } };
|
|
8327
8939
|
}
|
|
8328
8940
|
case "details": {
|
|
8329
8941
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8330
|
-
requireNoExtraArgs(remaining, "
|
|
8331
|
-
const requiredTask = requireTask(task, "
|
|
8942
|
+
requireNoExtraArgs(remaining, "rig task details --task <task-id>");
|
|
8943
|
+
const requiredTask = requireTask(task, "rig task details --task <task-id>");
|
|
8332
8944
|
await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, requiredTask));
|
|
8333
8945
|
return { ok: true, group: "task", command, details: { task: requiredTask } };
|
|
8334
8946
|
}
|
|
@@ -8336,9 +8948,9 @@ async function executeTask(context, args, options) {
|
|
|
8336
8948
|
const { value: task, rest: rest1 } = takeOption(rest, "--task");
|
|
8337
8949
|
const allFlag = takeFlag(rest1, "--all");
|
|
8338
8950
|
const { rest: remaining } = takeOption(allFlag.rest, "--reason");
|
|
8339
|
-
requireNoExtraArgs(remaining, "
|
|
8951
|
+
requireNoExtraArgs(remaining, "rig task reopen [--task <id> | --all] [--reason <text>]");
|
|
8340
8952
|
if (!allFlag.value && !task) {
|
|
8341
|
-
throw new CliError2("Usage:
|
|
8953
|
+
throw new CliError2("Usage: rig task reopen [--task <id> | --all] [--reason <text>]");
|
|
8342
8954
|
}
|
|
8343
8955
|
const summary = withMutedConsole(context.outputMode === "json", () => taskReopen(context.projectRoot, {
|
|
8344
8956
|
all: allFlag.value,
|
|
@@ -10373,15 +10985,15 @@ async function executeTest(context, args) {
|
|
|
10373
10985
|
const [command = "unit", ...rest] = args;
|
|
10374
10986
|
switch (command) {
|
|
10375
10987
|
case "unit":
|
|
10376
|
-
requireNoExtraArgs(rest, "
|
|
10988
|
+
requireNoExtraArgs(rest, "rig test unit");
|
|
10377
10989
|
await context.runCommand(["bun", "test", "tests/harness/", "--ignore", "tests/harness/e2e/**"]);
|
|
10378
10990
|
return { ok: true, group: "test", command };
|
|
10379
10991
|
case "e2e":
|
|
10380
|
-
requireNoExtraArgs(rest, "
|
|
10992
|
+
requireNoExtraArgs(rest, "rig test e2e");
|
|
10381
10993
|
await context.runCommand(["bun", "test", "tests/harness/e2e/"]);
|
|
10382
10994
|
return { ok: true, group: "test", command };
|
|
10383
10995
|
case "all":
|
|
10384
|
-
requireNoExtraArgs(rest, "
|
|
10996
|
+
requireNoExtraArgs(rest, "rig test all");
|
|
10385
10997
|
await context.runCommand(["bun", "test", "tests/harness/"]);
|
|
10386
10998
|
return { ok: true, group: "test", command };
|
|
10387
10999
|
default:
|
|
@@ -10401,7 +11013,7 @@ async function executeSetup(context, args) {
|
|
|
10401
11013
|
const [command = "check", ...rest] = args;
|
|
10402
11014
|
switch (command) {
|
|
10403
11015
|
case "bootstrap":
|
|
10404
|
-
requireNoExtraArgs(rest, "
|
|
11016
|
+
requireNoExtraArgs(rest, "rig setup bootstrap");
|
|
10405
11017
|
{
|
|
10406
11018
|
const hostBash = Bun.which("bash") || "/bin/bash";
|
|
10407
11019
|
const env = { ...process.env };
|
|
@@ -10424,21 +11036,21 @@ async function executeSetup(context, args) {
|
|
|
10424
11036
|
}
|
|
10425
11037
|
return { ok: true, group: "setup", command };
|
|
10426
11038
|
case "check":
|
|
10427
|
-
requireNoExtraArgs(rest, `
|
|
11039
|
+
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
10428
11040
|
{
|
|
10429
11041
|
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
10430
11042
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
10431
11043
|
}
|
|
10432
11044
|
case "setup":
|
|
10433
|
-
requireNoExtraArgs(rest, "
|
|
11045
|
+
requireNoExtraArgs(rest, "rig setup setup");
|
|
10434
11046
|
withMutedConsole(context.outputMode === "json", () => runSetupInit(context.projectRoot));
|
|
10435
11047
|
return { ok: true, group: "setup", command };
|
|
10436
11048
|
case "preflight":
|
|
10437
|
-
requireNoExtraArgs(rest, "
|
|
11049
|
+
requireNoExtraArgs(rest, "rig setup preflight");
|
|
10438
11050
|
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
10439
11051
|
return { ok: true, group: "setup", command };
|
|
10440
11052
|
case "install-agent-shell":
|
|
10441
|
-
requireNoExtraArgs(rest, "
|
|
11053
|
+
requireNoExtraArgs(rest, "rig setup install-agent-shell");
|
|
10442
11054
|
if (context.outputMode === "text") {
|
|
10443
11055
|
console.log("install-agent-shell is deprecated. Runtime shells now use compiled rig-agent directly.");
|
|
10444
11056
|
}
|
|
@@ -10503,7 +11115,7 @@ async function executeWorkspace(context, args) {
|
|
|
10503
11115
|
const [command = "summary", ...rest] = args;
|
|
10504
11116
|
switch (command) {
|
|
10505
11117
|
case "summary": {
|
|
10506
|
-
requireNoExtraArgs(rest, "
|
|
11118
|
+
requireNoExtraArgs(rest, "rig workspace summary");
|
|
10507
11119
|
const summary = await readWorkspaceSummary(context.projectRoot);
|
|
10508
11120
|
if (context.outputMode === "text") {
|
|
10509
11121
|
console.log("Workspace Summary");
|
|
@@ -10528,7 +11140,7 @@ Warnings:`);
|
|
|
10528
11140
|
return { ok: true, group: "workspace", command, details: summary };
|
|
10529
11141
|
}
|
|
10530
11142
|
case "topology": {
|
|
10531
|
-
requireNoExtraArgs(rest, "
|
|
11143
|
+
requireNoExtraArgs(rest, "rig workspace topology");
|
|
10532
11144
|
const topology = readWorkspaceTopology(context.projectRoot);
|
|
10533
11145
|
if (context.outputMode === "text") {
|
|
10534
11146
|
console.log(`Topology: ${topology.status}`);
|
|
@@ -10541,7 +11153,7 @@ Warnings:`);
|
|
|
10541
11153
|
return { ok: true, group: "workspace", command, details: topology };
|
|
10542
11154
|
}
|
|
10543
11155
|
case "remote-hosts": {
|
|
10544
|
-
requireNoExtraArgs(rest, "
|
|
11156
|
+
requireNoExtraArgs(rest, "rig workspace remote-hosts");
|
|
10545
11157
|
const fleet = readWorkspaceRemoteFleet(context.projectRoot);
|
|
10546
11158
|
if (context.outputMode === "text") {
|
|
10547
11159
|
console.log(`Remote Hosts: ${fleet.status}`);
|
|
@@ -10556,7 +11168,7 @@ Warnings:`);
|
|
|
10556
11168
|
let pending = serviceRest;
|
|
10557
11169
|
const services = takeOption(pending, "--service");
|
|
10558
11170
|
pending = services.rest;
|
|
10559
|
-
requireNoExtraArgs(pending, "
|
|
11171
|
+
requireNoExtraArgs(pending, "rig workspace service-fabric <status|up|verify|down> [--service <name>]");
|
|
10560
11172
|
if (action !== "status" && action !== "up" && action !== "verify" && action !== "down") {
|
|
10561
11173
|
throw new CliError2(`Unknown workspace service-fabric action: ${action}`);
|
|
10562
11174
|
}
|
|
@@ -10577,171 +11189,6 @@ Warnings:`);
|
|
|
10577
11189
|
}
|
|
10578
11190
|
}
|
|
10579
11191
|
|
|
10580
|
-
// packages/cli/src/commands/_help-catalog.ts
|
|
10581
|
-
import pc4 from "picocolors";
|
|
10582
|
-
var PRIMARY_GROUPS = [
|
|
10583
|
-
{
|
|
10584
|
-
name: "server",
|
|
10585
|
-
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
10586
|
-
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
10587
|
-
commands: [
|
|
10588
|
-
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
10589
|
-
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
10590
|
-
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
10591
|
-
{ command: "use [alias|local]", description: "Select a server; prompts in an interactive TTY.", primary: true },
|
|
10592
|
-
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process.", primary: true }
|
|
10593
|
-
],
|
|
10594
|
-
examples: [
|
|
10595
|
-
"rig server status",
|
|
10596
|
-
"rig server add prod https://where.rig-does.work",
|
|
10597
|
-
"rig server use prod",
|
|
10598
|
-
"rig server use local",
|
|
10599
|
-
"rig server start --port 3773"
|
|
10600
|
-
],
|
|
10601
|
-
next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
|
|
10602
|
-
advanced: ["Compatibility alias: `rig connect ...` remains callable."]
|
|
10603
|
-
},
|
|
10604
|
-
{
|
|
10605
|
-
name: "task",
|
|
10606
|
-
summary: "Find work, start Pi-backed runs, and validate task results.",
|
|
10607
|
-
usage: ["rig task <list|next|show|run> [options]"],
|
|
10608
|
-
commands: [
|
|
10609
|
-
{ command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
|
|
10610
|
-
{ command: "next [filters]", description: "Pick the next matching task.", primary: true },
|
|
10611
|
-
{ command: "show <id>|--task <id>", description: "Show task details.", primary: true },
|
|
10612
|
-
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
10613
|
-
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
10614
|
-
{ command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
|
|
10615
|
-
{ command: "report-bug", description: "Create a structured bug report/task." }
|
|
10616
|
-
],
|
|
10617
|
-
examples: [
|
|
10618
|
-
"rig task list --assignee @me --limit 20",
|
|
10619
|
-
"rig task run --next",
|
|
10620
|
-
"rig task run #123 --runtime-adapter pi",
|
|
10621
|
-
"rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
|
|
10622
|
-
],
|
|
10623
|
-
next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
|
|
10624
|
-
},
|
|
10625
|
-
{
|
|
10626
|
-
name: "run",
|
|
10627
|
-
summary: "Observe, attach to, and control Rig runs.",
|
|
10628
|
-
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
10629
|
-
commands: [
|
|
10630
|
-
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
10631
|
-
{ command: "status", description: "Summarize active and recent runs.", primary: true },
|
|
10632
|
-
{ command: "show --run <id>", description: "Show one run record.", primary: true },
|
|
10633
|
-
{ command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; `--follow` launches native bundled Pi for live Pi runs.", primary: true },
|
|
10634
|
-
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
10635
|
-
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
10636
|
-
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
10637
|
-
],
|
|
10638
|
-
examples: [
|
|
10639
|
-
"rig run list",
|
|
10640
|
-
"rig run attach 01234567-89ab-cdef-0123-456789abcdef --follow",
|
|
10641
|
-
"rig run show --run <run-id>",
|
|
10642
|
-
"rig run stop <run-id>"
|
|
10643
|
-
],
|
|
10644
|
-
next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
|
|
10645
|
-
}
|
|
10646
|
-
];
|
|
10647
|
-
var ADVANCED_GROUPS = [
|
|
10648
|
-
{ name: "init", summary: "Initialize or repair Rig project state.", usage: ["rig init [options]"], commands: [{ command: "init", description: "Configure project/server/GitHub integration." }] },
|
|
10649
|
-
{ 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." }] },
|
|
10650
|
-
{ name: "github", summary: "GitHub auth helpers.", usage: ["rig github auth <status|import-gh|token>"], commands: [{ command: "auth status", description: "Show GitHub auth state." }] },
|
|
10651
|
-
{ name: "doctor", summary: "Diagnostics for project/server/GitHub/Pi state.", usage: ["rig doctor [check|run|shared|...]"], commands: [{ command: "check", description: "Run diagnostics." }] },
|
|
10652
|
-
{ name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
|
|
10653
|
-
{ 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." }] },
|
|
10654
|
-
{ name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
|
|
10655
|
-
{ name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
|
|
10656
|
-
{ name: "review", summary: "Review policy configuration.", usage: ["rig review <show|set>"], commands: [{ command: "show", description: "Show review settings." }] },
|
|
10657
|
-
{ name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
|
|
10658
|
-
{ name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
|
|
10659
|
-
{ name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
|
|
10660
|
-
{ name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
|
|
10661
|
-
{ name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
|
|
10662
|
-
{ name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
|
|
10663
|
-
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
10664
|
-
{ name: "remote", summary: "Legacy remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
|
|
10665
|
-
{ name: "inbox", summary: "Approval/input inbox for blocked runs.", usage: ["rig inbox <approvals|approve|inputs|respond>"], commands: [{ command: "approvals", description: "List pending approvals." }] },
|
|
10666
|
-
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
10667
|
-
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
10668
|
-
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
10669
|
-
];
|
|
10670
|
-
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
10671
|
-
function heading(title) {
|
|
10672
|
-
return pc4.bold(pc4.cyan(title));
|
|
10673
|
-
}
|
|
10674
|
-
function commandLine(command, description) {
|
|
10675
|
-
const commandColumn = command.length >= 34 ? `${command} ` : command.padEnd(34);
|
|
10676
|
-
return ` ${pc4.bold(commandColumn)} ${description}`;
|
|
10677
|
-
}
|
|
10678
|
-
function renderGroup(group) {
|
|
10679
|
-
const lines = [
|
|
10680
|
-
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
10681
|
-
"",
|
|
10682
|
-
pc4.bold("Usage"),
|
|
10683
|
-
...group.usage.map((line) => ` ${line}`),
|
|
10684
|
-
"",
|
|
10685
|
-
pc4.bold("Commands"),
|
|
10686
|
-
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
10687
|
-
];
|
|
10688
|
-
if (group.examples?.length) {
|
|
10689
|
-
lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
|
|
10690
|
-
}
|
|
10691
|
-
if (group.next?.length) {
|
|
10692
|
-
lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
10693
|
-
}
|
|
10694
|
-
if (group.advanced?.length) {
|
|
10695
|
-
lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
10696
|
-
}
|
|
10697
|
-
return lines.join(`
|
|
10698
|
-
`);
|
|
10699
|
-
}
|
|
10700
|
-
function renderTopLevelHelp() {
|
|
10701
|
-
return [
|
|
10702
|
-
`${heading("rig")} \u2014 server-owned task/run control plane`,
|
|
10703
|
-
"",
|
|
10704
|
-
pc4.bold("Common workflows"),
|
|
10705
|
-
" rig server status Show selected local/remote server",
|
|
10706
|
-
" rig task list List available work",
|
|
10707
|
-
" rig task run --next Start next task and attach with native Pi",
|
|
10708
|
-
" rig run list List recent runs",
|
|
10709
|
-
" rig run attach <run-id> --follow Rejoin a live run",
|
|
10710
|
-
"",
|
|
10711
|
-
pc4.bold("Primary groups"),
|
|
10712
|
-
...PRIMARY_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
10713
|
-
"",
|
|
10714
|
-
pc4.bold("Help"),
|
|
10715
|
-
" rig <group> --help Rich help for server, task, run, and other groups",
|
|
10716
|
-
" rig help --advanced Legacy/dev/compat command surface",
|
|
10717
|
-
" rig --version Print version",
|
|
10718
|
-
"",
|
|
10719
|
-
pc4.bold("Global options"),
|
|
10720
|
-
" --project <path> Use a project root instead of auto-discovery",
|
|
10721
|
-
" --json Output structured JSON",
|
|
10722
|
-
" --dry-run Print command execution plan only"
|
|
10723
|
-
].join(`
|
|
10724
|
-
`);
|
|
10725
|
-
}
|
|
10726
|
-
function renderAdvancedHelp() {
|
|
10727
|
-
return [
|
|
10728
|
-
`${heading("rig advanced")} \u2014 legacy, dev, and compatibility groups`,
|
|
10729
|
-
"",
|
|
10730
|
-
pc4.bold("Primary groups are still"),
|
|
10731
|
-
" server, task, run",
|
|
10732
|
-
"",
|
|
10733
|
-
pc4.bold("Advanced groups"),
|
|
10734
|
-
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
10735
|
-
"",
|
|
10736
|
-
pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, and `rig run` for day-to-day work.")
|
|
10737
|
-
].join(`
|
|
10738
|
-
`);
|
|
10739
|
-
}
|
|
10740
|
-
function renderGroupHelp(groupName) {
|
|
10741
|
-
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
10742
|
-
return group ? renderGroup(group) : null;
|
|
10743
|
-
}
|
|
10744
|
-
|
|
10745
11192
|
// packages/cli/src/commands.ts
|
|
10746
11193
|
import { ensureProjectMainFreshBeforeRun as ensureProjectMainFreshBeforeRun2 } from "@rig/runtime/control-plane/project-main-pre-run-sync";
|
|
10747
11194
|
var TOP_LEVEL_ALIASES = {
|
|
@@ -10753,7 +11200,7 @@ var TOP_LEVEL_ALIASES = {
|
|
|
10753
11200
|
status: ["run", "status"],
|
|
10754
11201
|
start: ["task", "run", "--next"],
|
|
10755
11202
|
"start-parallel": ["run", "start-parallel"],
|
|
10756
|
-
"start-serial": ["
|
|
11203
|
+
"start-serial": ["run", "start-serial"],
|
|
10757
11204
|
resume: ["run", "resume"],
|
|
10758
11205
|
stop: ["run", "stop"],
|
|
10759
11206
|
ready: ["task", "ready"],
|
|
@@ -10809,7 +11256,7 @@ var GROUPS = new Set([
|
|
|
10809
11256
|
"test"
|
|
10810
11257
|
]);
|
|
10811
11258
|
function printGroupHelp(group) {
|
|
10812
|
-
|
|
11259
|
+
printGroupHelpDocument(group);
|
|
10813
11260
|
}
|
|
10814
11261
|
function isHelpArg(arg) {
|
|
10815
11262
|
return arg === "--help" || arg === "-h" || arg === "help";
|
|
@@ -10819,7 +11266,7 @@ function helpText() {
|
|
|
10819
11266
|
}
|
|
10820
11267
|
async function execute(context, args) {
|
|
10821
11268
|
if (args.length === 0) {
|
|
10822
|
-
|
|
11269
|
+
printTopLevelHelp();
|
|
10823
11270
|
return { ok: true, group: "help", command: "show" };
|
|
10824
11271
|
}
|
|
10825
11272
|
const [first, ...rest] = args;
|
|
@@ -10830,14 +11277,14 @@ ${helpText()}`);
|
|
|
10830
11277
|
}
|
|
10831
11278
|
if (first === "help" || first === "--help" || first === "-h") {
|
|
10832
11279
|
if (rest[0] === "--advanced") {
|
|
10833
|
-
|
|
11280
|
+
printAdvancedHelp();
|
|
10834
11281
|
return { ok: true, group: "help", command: "advanced" };
|
|
10835
11282
|
}
|
|
10836
11283
|
if (rest[0]) {
|
|
10837
|
-
|
|
11284
|
+
printGroupHelp(rest[0]);
|
|
10838
11285
|
return { ok: true, group: "help", command: rest[0] };
|
|
10839
11286
|
}
|
|
10840
|
-
|
|
11287
|
+
printTopLevelHelp();
|
|
10841
11288
|
return { ok: true, group: "help", command: "show" };
|
|
10842
11289
|
}
|
|
10843
11290
|
if (first === "--version" || first === "-V" || first === "version") {
|