@h-rig/cli 0.0.6-alpha.27 → 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 +1038 -620
- 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 +225 -64
- 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 +1038 -620
- package/dist/src/index.js +1038 -620
- package/dist/src/report-bug.js +3 -3
- package/package.json +6 -6
package/dist/src/index.js
CHANGED
|
@@ -491,15 +491,15 @@ function buildBugReportMarkdown(input, browser, screenshots, assets) {
|
|
|
491
491
|
...input.issueId ? [
|
|
492
492
|
`- Canonical task assets live under \`artifacts/${input.issueId}/bug-report/\`.`,
|
|
493
493
|
`- Start with \`artifacts/${input.issueId}/bug-report/task.md\` and the files in \`artifacts/${input.issueId}/bug-report/assets/\`.`,
|
|
494
|
-
browserRequired ? `- Run \`
|
|
494
|
+
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.`
|
|
495
495
|
] : [
|
|
496
|
-
"- Draft-only report: convert this into a
|
|
496
|
+
"- Draft-only report: convert this into a Rig task before assigning it to an agent run."
|
|
497
497
|
],
|
|
498
498
|
"",
|
|
499
499
|
"## Validation",
|
|
500
500
|
"",
|
|
501
501
|
"```bash",
|
|
502
|
-
...input.issueId ? [`
|
|
502
|
+
...input.issueId ? [`rig task validate --task ${input.issueId}`] : [],
|
|
503
503
|
...browserRequired ? [
|
|
504
504
|
"bun run app:check:browser:hp-next",
|
|
505
505
|
"bun run app:e2e:browser:hp-next"
|
|
@@ -646,7 +646,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
646
646
|
pending = outputRootResult.rest;
|
|
647
647
|
const slugResult = takeOption(pending, "--slug");
|
|
648
648
|
pending = slugResult.rest;
|
|
649
|
-
requireNoExtraArgs(pending, "
|
|
649
|
+
requireNoExtraArgs(pending, "rig report-bug [--no-prompt] [--no-beads] [--browser|--no-browser] --title <text> --url <url> [--asset <dragged-file>]");
|
|
650
650
|
let draft = {
|
|
651
651
|
outputRoot: outputRootResult.value || "",
|
|
652
652
|
title: titleResult.value,
|
|
@@ -751,7 +751,7 @@ async function executeTaskReportBug(context, args) {
|
|
|
751
751
|
console.log(`Evidence assets: ${result.assetDir}`);
|
|
752
752
|
if (taskConfigPath) {
|
|
753
753
|
console.log(`Task config: ${taskConfigPath}`);
|
|
754
|
-
console.log(`Run:
|
|
754
|
+
console.log(`Run: rig task info --task ${issueId}`);
|
|
755
755
|
}
|
|
756
756
|
}
|
|
757
757
|
return {
|
|
@@ -1574,7 +1574,7 @@ async function executeBrowser(context, args) {
|
|
|
1574
1574
|
return { ok: true, group: "browser", command: "help" };
|
|
1575
1575
|
}
|
|
1576
1576
|
if (command === "explain") {
|
|
1577
|
-
requireNoExtraArgs(rest, "
|
|
1577
|
+
requireNoExtraArgs(rest, "rig browser explain");
|
|
1578
1578
|
console.log(browserAgentUsageText());
|
|
1579
1579
|
return { ok: true, group: "browser", command: "explain" };
|
|
1580
1580
|
}
|
|
@@ -1600,7 +1600,7 @@ ${browserHelpText()}`);
|
|
|
1600
1600
|
|
|
1601
1601
|
${browserHelpText()}`);
|
|
1602
1602
|
}
|
|
1603
|
-
requireNoExtraArgs(appRest, `
|
|
1603
|
+
requireNoExtraArgs(appRest, `rig browser ${command} ${subcommand}`);
|
|
1604
1604
|
await context.runCommand(["bun", "run", `app:${subcommand}:browser:${appSlug}`]);
|
|
1605
1605
|
return { ok: true, group: "browser", command: `${command}-${subcommand}` };
|
|
1606
1606
|
}
|
|
@@ -1612,7 +1612,7 @@ ${browserHelpText()}`);
|
|
|
1612
1612
|
};
|
|
1613
1613
|
const packageScript = packageScripts[command];
|
|
1614
1614
|
if (packageScript) {
|
|
1615
|
-
requireNoExtraArgs(rest, `
|
|
1615
|
+
requireNoExtraArgs(rest, `rig browser ${command}`);
|
|
1616
1616
|
await context.runCommand(["bun", "run", "--filter=@rig/browser", packageScript]);
|
|
1617
1617
|
return { ok: true, group: "browser", command };
|
|
1618
1618
|
}
|
|
@@ -1639,7 +1639,7 @@ async function executeBrowserDemo(context, args) {
|
|
|
1639
1639
|
pending = keepOpenFlag.rest;
|
|
1640
1640
|
const noBuildFlag = takeFlag(pending, "--no-build");
|
|
1641
1641
|
pending = noBuildFlag.rest;
|
|
1642
|
-
requireNoExtraArgs(pending, "
|
|
1642
|
+
requireNoExtraArgs(pending, "rig browser demo [--port <n>] [--profile <name>] [--state-dir <path>] [--target-url <url>] [--keep-open] [--no-build]");
|
|
1643
1643
|
if (context.outputMode !== "text" || !process.stdin.isTTY || !process.stdout.isTTY) {
|
|
1644
1644
|
throw new CliError2("rig browser demo requires an interactive TTY in text mode.");
|
|
1645
1645
|
}
|
|
@@ -2150,17 +2150,17 @@ async function executeProfile(context, args) {
|
|
|
2150
2150
|
const [command = "show", ...rest] = args;
|
|
2151
2151
|
switch (command) {
|
|
2152
2152
|
case "show":
|
|
2153
|
-
requireNoExtraArgs(rest, "
|
|
2153
|
+
requireNoExtraArgs(rest, "rig profile show");
|
|
2154
2154
|
await withMutedConsole(context.outputMode === "json", () => showProfile(context.projectRoot));
|
|
2155
2155
|
return { ok: true, group: "profile", command };
|
|
2156
2156
|
case "set": {
|
|
2157
2157
|
if (rest.length === 0) {
|
|
2158
|
-
throw new CliError2("Usage:
|
|
2158
|
+
throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi> or set [--model ...] [--runtime ...] [--plugin ...]");
|
|
2159
2159
|
}
|
|
2160
2160
|
const preset = rest[0];
|
|
2161
2161
|
if (preset && !preset.startsWith("-")) {
|
|
2162
2162
|
if (rest.length !== 1) {
|
|
2163
|
-
throw new CliError2("Usage:
|
|
2163
|
+
throw new CliError2("Usage: rig profile set <claude-code|codex-cli|pi>");
|
|
2164
2164
|
}
|
|
2165
2165
|
try {
|
|
2166
2166
|
await withMutedConsole(context.outputMode === "json", () => setProfile(context.projectRoot, { preset }));
|
|
@@ -2176,7 +2176,7 @@ async function executeProfile(context, args) {
|
|
|
2176
2176
|
pending = runtimeResult.rest;
|
|
2177
2177
|
const pluginResult = takeOption(pending, "--plugin");
|
|
2178
2178
|
pending = pluginResult.rest;
|
|
2179
|
-
requireNoExtraArgs(pending, "
|
|
2179
|
+
requireNoExtraArgs(pending, "rig profile set [--model ...] [--runtime ...] [--plugin ...]");
|
|
2180
2180
|
if (!modelResult.value && !runtimeResult.value && !pluginResult.value) {
|
|
2181
2181
|
throw new CliError2("Provide at least one of --model, --runtime, or --plugin.");
|
|
2182
2182
|
}
|
|
@@ -2208,21 +2208,21 @@ async function executeReview(context, args) {
|
|
|
2208
2208
|
const [command = "show", ...rest] = args;
|
|
2209
2209
|
switch (command) {
|
|
2210
2210
|
case "show":
|
|
2211
|
-
requireNoExtraArgs(rest, "
|
|
2211
|
+
requireNoExtraArgs(rest, "rig review show");
|
|
2212
2212
|
await withMutedConsole(context.outputMode === "json", () => showReviewProfile(context.projectRoot));
|
|
2213
2213
|
return { ok: true, group: "review", command };
|
|
2214
2214
|
case "set": {
|
|
2215
2215
|
if (rest.length === 0) {
|
|
2216
|
-
throw new CliError2("Usage:
|
|
2216
|
+
throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
|
|
2217
2217
|
}
|
|
2218
2218
|
const mode = rest[0];
|
|
2219
2219
|
if (!mode) {
|
|
2220
|
-
throw new CliError2("Usage:
|
|
2220
|
+
throw new CliError2("Usage: rig review set <off|advisory|required> [--provider greptile]");
|
|
2221
2221
|
}
|
|
2222
2222
|
let pending = rest.slice(1);
|
|
2223
2223
|
const providerResult = takeOption(pending, "--provider");
|
|
2224
2224
|
pending = providerResult.rest;
|
|
2225
|
-
requireNoExtraArgs(pending, "
|
|
2225
|
+
requireNoExtraArgs(pending, "rig review set <off|advisory|required> [--provider greptile]");
|
|
2226
2226
|
try {
|
|
2227
2227
|
await withMutedConsole(context.outputMode === "json", () => {
|
|
2228
2228
|
return setReviewProfile(context.projectRoot, mode, providerResult.value);
|
|
@@ -2307,13 +2307,13 @@ async function executeRepo(context, args) {
|
|
|
2307
2307
|
switch (command) {
|
|
2308
2308
|
case "sync": {
|
|
2309
2309
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
2310
|
-
requireNoExtraArgs(remaining, "
|
|
2310
|
+
requireNoExtraArgs(remaining, "rig repo sync [--task <task-id>]");
|
|
2311
2311
|
withMutedConsole(context.outputMode === "json", () => repoEnsure(context.projectRoot, task || undefined));
|
|
2312
2312
|
return { ok: true, group: "repo", command, details: { task: task || null } };
|
|
2313
2313
|
}
|
|
2314
2314
|
case "reset-baseline": {
|
|
2315
2315
|
const { value: keepTaskStatusFlag, rest: remaining } = takeFlag(rest, "--keep-task-status");
|
|
2316
|
-
requireNoExtraArgs(remaining, "
|
|
2316
|
+
requireNoExtraArgs(remaining, "rig repo reset-baseline [--keep-task-status]");
|
|
2317
2317
|
withMutedConsole(context.outputMode === "json", () => resetBaseline(context.projectRoot, keepTaskStatusFlag));
|
|
2318
2318
|
return { ok: true, group: "repo", command, details: { keepTaskStatus: keepTaskStatusFlag } };
|
|
2319
2319
|
}
|
|
@@ -2323,7 +2323,7 @@ async function executeRepo(context, args) {
|
|
|
2323
2323
|
}
|
|
2324
2324
|
async function executeGit(context, args) {
|
|
2325
2325
|
if (args.length === 0) {
|
|
2326
|
-
throw new CliError2("Usage:
|
|
2326
|
+
throw new CliError2("Usage: rig git <git-flow args...>");
|
|
2327
2327
|
}
|
|
2328
2328
|
await enforceNativeCommandPolicy(context, args, {
|
|
2329
2329
|
commandPrefix: "rig-agent git",
|
|
@@ -2344,7 +2344,7 @@ async function executeGit(context, args) {
|
|
|
2344
2344
|
}
|
|
2345
2345
|
async function executeHarness(context, args) {
|
|
2346
2346
|
if (args.length === 0) {
|
|
2347
|
-
throw new CliError2("Usage:
|
|
2347
|
+
throw new CliError2("Usage: rig harness <harness args...>");
|
|
2348
2348
|
}
|
|
2349
2349
|
await enforceNativeCommandPolicy(context, args, {
|
|
2350
2350
|
commandPrefix: "rig-agent",
|
|
@@ -2453,7 +2453,7 @@ async function executePlugin(context, args) {
|
|
|
2453
2453
|
const [command = "list", ...rest] = args;
|
|
2454
2454
|
switch (command) {
|
|
2455
2455
|
case "list": {
|
|
2456
|
-
requireNoExtraArgs(rest, "
|
|
2456
|
+
requireNoExtraArgs(rest, "rig plugin list");
|
|
2457
2457
|
const legacyPlugins = context.plugins.list();
|
|
2458
2458
|
const declarative = [];
|
|
2459
2459
|
const config = await loadRigConfigOrNull(context.projectRoot);
|
|
@@ -2520,8 +2520,8 @@ async function executePlugin(context, args) {
|
|
|
2520
2520
|
}
|
|
2521
2521
|
case "validate": {
|
|
2522
2522
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
2523
|
-
requireNoExtraArgs(remaining, "
|
|
2524
|
-
const taskId = requireTask(task, "
|
|
2523
|
+
requireNoExtraArgs(remaining, "rig plugin validate --task <task-id>");
|
|
2524
|
+
const taskId = requireTask(task, "rig plugin validate --task <task-id>");
|
|
2525
2525
|
const results = await context.plugins.runValidators(taskId);
|
|
2526
2526
|
const passed = results.filter((result) => result.passed).length;
|
|
2527
2527
|
const failed = results.length - passed;
|
|
@@ -2661,7 +2661,7 @@ function resolveSelectedConnection(projectRoot, options = {}) {
|
|
|
2661
2661
|
const global = readGlobalConnections(options);
|
|
2662
2662
|
const connection = global.connections[repo.selected];
|
|
2663
2663
|
if (!connection) {
|
|
2664
|
-
throw new CliError2(`Selected Rig
|
|
2664
|
+
throw new CliError2(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
|
|
2665
2665
|
}
|
|
2666
2666
|
return { alias: repo.selected, connection };
|
|
2667
2667
|
}
|
|
@@ -3153,7 +3153,7 @@ async function runFastTaskRunPreflight(context, options = {}) {
|
|
|
3153
3153
|
}
|
|
3154
3154
|
}
|
|
3155
3155
|
const repo = readRepoConnection(context.projectRoot);
|
|
3156
|
-
checks.push(repo ? preflightCheck("project-link", "project linked to Rig
|
|
3156
|
+
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>`."));
|
|
3157
3157
|
try {
|
|
3158
3158
|
const auth = await request("/api/github/auth/status");
|
|
3159
3159
|
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>`."));
|
|
@@ -3271,7 +3271,7 @@ async function executeQueue(context, args) {
|
|
|
3271
3271
|
pending = failFastResult.rest;
|
|
3272
3272
|
const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
|
|
3273
3273
|
pending = skipProjectSyncResult.rest;
|
|
3274
|
-
requireNoExtraArgs(pending, "
|
|
3274
|
+
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]");
|
|
3275
3275
|
const workers = parsePositiveInt(workersResult.value, "--workers", 2);
|
|
3276
3276
|
const maxTasks = parsePositiveInt(maxTasksResult.value, "--max-tasks", 10);
|
|
3277
3277
|
const action = parseAction(actionResult.value);
|
|
@@ -3449,7 +3449,7 @@ async function executeAgent(context, args) {
|
|
|
3449
3449
|
const [command = "list", ...rest] = args;
|
|
3450
3450
|
switch (command) {
|
|
3451
3451
|
case "list": {
|
|
3452
|
-
requireNoExtraArgs(rest, "
|
|
3452
|
+
requireNoExtraArgs(rest, "rig agent list");
|
|
3453
3453
|
const runtimes = await listAgentRuntimes(context.projectRoot);
|
|
3454
3454
|
if (context.outputMode === "text") {
|
|
3455
3455
|
if (runtimes.length === 0) {
|
|
@@ -3470,12 +3470,12 @@ async function executeAgent(context, args) {
|
|
|
3470
3470
|
pending = modeResult.rest;
|
|
3471
3471
|
const taskResult = takeOption(pending, "--task");
|
|
3472
3472
|
pending = taskResult.rest;
|
|
3473
|
-
requireNoExtraArgs(pending, "
|
|
3473
|
+
requireNoExtraArgs(pending, "rig agent prepare --task <id> [--id <id>] [--mode worktree]");
|
|
3474
3474
|
const mode = parseIsolationMode(modeResult.value, false);
|
|
3475
3475
|
const id = idResult.value || agentId("agent");
|
|
3476
3476
|
const taskId = taskResult.value?.trim();
|
|
3477
3477
|
if (!taskId) {
|
|
3478
|
-
throw new CliError2("Usage:
|
|
3478
|
+
throw new CliError2("Usage: rig agent prepare --task <id> [--id <id>] [--mode worktree]");
|
|
3479
3479
|
}
|
|
3480
3480
|
const runtime = await withMutedConsole(context.outputMode === "json", () => ensureAgentRuntime({
|
|
3481
3481
|
projectRoot: context.projectRoot,
|
|
@@ -3493,7 +3493,7 @@ async function executeAgent(context, args) {
|
|
|
3493
3493
|
case "run": {
|
|
3494
3494
|
const { options, commandParts } = splitAtDoubleDash(rest);
|
|
3495
3495
|
if (commandParts.length === 0) {
|
|
3496
|
-
throw new CliError2("Usage:
|
|
3496
|
+
throw new CliError2("Usage: rig agent run [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3497
3497
|
}
|
|
3498
3498
|
let pending = options;
|
|
3499
3499
|
const idResult = takeOption(pending, "--id");
|
|
@@ -3504,12 +3504,12 @@ async function executeAgent(context, args) {
|
|
|
3504
3504
|
pending = taskResult.rest;
|
|
3505
3505
|
const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
|
|
3506
3506
|
pending = skipProjectSyncResult.rest;
|
|
3507
|
-
requireNoExtraArgs(pending, "
|
|
3507
|
+
requireNoExtraArgs(pending, "rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3508
3508
|
const mode = parseIsolationMode(modeResult.value, false);
|
|
3509
3509
|
const id = idResult.value || agentId("agent-run");
|
|
3510
3510
|
const taskId = taskResult.value?.trim();
|
|
3511
3511
|
if (!taskId) {
|
|
3512
|
-
throw new CliError2("Usage:
|
|
3512
|
+
throw new CliError2("Usage: rig agent run --task <id> [--id <id>] [--mode worktree] [--skip-project-sync] -- <command...>");
|
|
3513
3513
|
}
|
|
3514
3514
|
await runProjectMainSyncPreflight(context, { disabled: skipProjectSyncResult.value });
|
|
3515
3515
|
const createdAt = new Date().toISOString();
|
|
@@ -3623,7 +3623,7 @@ ${result.stderr.trim()}` : ""}`, result.exitCode);
|
|
|
3623
3623
|
pending = allResult.rest;
|
|
3624
3624
|
const idResult = takeOption(pending, "--id");
|
|
3625
3625
|
pending = idResult.rest;
|
|
3626
|
-
requireNoExtraArgs(pending, "
|
|
3626
|
+
requireNoExtraArgs(pending, "rig agent cleanup (--id <id> | --all)");
|
|
3627
3627
|
if (!allResult.value && !idResult.value) {
|
|
3628
3628
|
throw new CliError2("Provide --id <id> or --all.");
|
|
3629
3629
|
}
|
|
@@ -3759,7 +3759,7 @@ async function executeDist(context, args) {
|
|
|
3759
3759
|
switch (command) {
|
|
3760
3760
|
case "build": {
|
|
3761
3761
|
const { value: outputDir, rest: pending } = takeOption(rest, "--output-dir");
|
|
3762
|
-
requireNoExtraArgs(pending, "
|
|
3762
|
+
requireNoExtraArgs(pending, "rig dist build [--output-dir <dir>]");
|
|
3763
3763
|
const commandParts = ["bun", "run", "packages/cli/bin/build-rig-binaries.ts"];
|
|
3764
3764
|
if (outputDir) {
|
|
3765
3765
|
commandParts.push("--output-dir", outputDir);
|
|
@@ -3773,7 +3773,7 @@ async function executeDist(context, args) {
|
|
|
3773
3773
|
pending = scopeResult.rest;
|
|
3774
3774
|
const pathResult = takeOption(pending, "--path");
|
|
3775
3775
|
pending = pathResult.rest;
|
|
3776
|
-
requireNoExtraArgs(pending, "
|
|
3776
|
+
requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
|
|
3777
3777
|
const scope = parseInstallScope(scopeResult.value);
|
|
3778
3778
|
const installDir = resolveInstallDir(scope, pathResult.value);
|
|
3779
3779
|
mkdirSync6(installDir, { recursive: true });
|
|
@@ -3816,7 +3816,7 @@ async function executeDist(context, args) {
|
|
|
3816
3816
|
};
|
|
3817
3817
|
}
|
|
3818
3818
|
case "doctor": {
|
|
3819
|
-
requireNoExtraArgs(rest, "
|
|
3819
|
+
requireNoExtraArgs(rest, "rig dist doctor");
|
|
3820
3820
|
const details = await runDistDoctor(context.projectRoot);
|
|
3821
3821
|
if (context.outputMode === "text") {
|
|
3822
3822
|
console.log(`bun: ${details.bun.available ? `ok (${details.bun.version})` : "missing"}`);
|
|
@@ -3827,7 +3827,7 @@ async function executeDist(context, args) {
|
|
|
3827
3827
|
return { ok: true, group: "dist", command, details };
|
|
3828
3828
|
}
|
|
3829
3829
|
case "rebuild-agent": {
|
|
3830
|
-
requireNoExtraArgs(rest, "
|
|
3830
|
+
requireNoExtraArgs(rest, "rig dist rebuild-agent");
|
|
3831
3831
|
const fp = await computeRuntimeImageFingerprint(context.projectRoot);
|
|
3832
3832
|
const currentId = computeRuntimeImageId(fp);
|
|
3833
3833
|
const imagesDir = resolve12(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
|
|
@@ -3979,6 +3979,414 @@ import {
|
|
|
3979
3979
|
readJsonlFile as readJsonlFile3,
|
|
3980
3980
|
resolveAuthorityRunDir as resolveAuthorityRunDir2
|
|
3981
3981
|
} from "@rig/runtime/control-plane/authority-files";
|
|
3982
|
+
|
|
3983
|
+
// packages/cli/src/commands/_cli-format.ts
|
|
3984
|
+
import { log as log3, note as note3 } from "@clack/prompts";
|
|
3985
|
+
import pc3 from "picocolors";
|
|
3986
|
+
function stringField(record, key, fallback = "") {
|
|
3987
|
+
const value = record[key];
|
|
3988
|
+
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
3989
|
+
}
|
|
3990
|
+
function numberField(record, key) {
|
|
3991
|
+
const value = record[key];
|
|
3992
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
3993
|
+
}
|
|
3994
|
+
function arrayField(record, key) {
|
|
3995
|
+
const value = record[key];
|
|
3996
|
+
return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
|
|
3997
|
+
}
|
|
3998
|
+
function rawObject(record) {
|
|
3999
|
+
const raw = record.raw;
|
|
4000
|
+
return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
4001
|
+
}
|
|
4002
|
+
function truncate(value, width) {
|
|
4003
|
+
if (value.length <= width)
|
|
4004
|
+
return value;
|
|
4005
|
+
if (width <= 1)
|
|
4006
|
+
return "\u2026";
|
|
4007
|
+
return `${value.slice(0, width - 1)}\u2026`;
|
|
4008
|
+
}
|
|
4009
|
+
function pad(value, width) {
|
|
4010
|
+
return value.length >= width ? value : `${value}${" ".repeat(width - value.length)}`;
|
|
4011
|
+
}
|
|
4012
|
+
function statusColor(status) {
|
|
4013
|
+
const normalized = status.toLowerCase();
|
|
4014
|
+
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected", "approved"].includes(normalized))
|
|
4015
|
+
return pc3.green;
|
|
4016
|
+
if (["failed", "needs_attention", "needs-attention", "blocked", "error", "rejected"].includes(normalized))
|
|
4017
|
+
return pc3.red;
|
|
4018
|
+
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
4019
|
+
return pc3.cyan;
|
|
4020
|
+
if (["ready", "open", "queued", "created", "preparing", "local", "pending"].includes(normalized))
|
|
4021
|
+
return pc3.yellow;
|
|
4022
|
+
return pc3.dim;
|
|
4023
|
+
}
|
|
4024
|
+
function compactDate(value) {
|
|
4025
|
+
if (!value.trim())
|
|
4026
|
+
return "";
|
|
4027
|
+
const parsed = Date.parse(value);
|
|
4028
|
+
if (!Number.isFinite(parsed))
|
|
4029
|
+
return value;
|
|
4030
|
+
return new Date(parsed).toISOString().replace("T", " ").replace(/\.\d{3}Z$/, "Z");
|
|
4031
|
+
}
|
|
4032
|
+
function compactValue(value) {
|
|
4033
|
+
if (value === null || value === undefined)
|
|
4034
|
+
return "";
|
|
4035
|
+
if (typeof value === "string")
|
|
4036
|
+
return value;
|
|
4037
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
4038
|
+
return String(value);
|
|
4039
|
+
if (Array.isArray(value))
|
|
4040
|
+
return value.map(compactValue).filter(Boolean).join(", ");
|
|
4041
|
+
return JSON.stringify(value);
|
|
4042
|
+
}
|
|
4043
|
+
function firstString(record, keys, fallback = "") {
|
|
4044
|
+
for (const key of keys) {
|
|
4045
|
+
const value = stringField(record, key);
|
|
4046
|
+
if (value)
|
|
4047
|
+
return value;
|
|
4048
|
+
}
|
|
4049
|
+
return fallback;
|
|
4050
|
+
}
|
|
4051
|
+
function runIdOf(run) {
|
|
4052
|
+
return firstString(run, ["runId", "id"], "(unknown-run)");
|
|
4053
|
+
}
|
|
4054
|
+
function taskIdOf(run) {
|
|
4055
|
+
return firstString(run, ["taskId", "task", "task_id"]);
|
|
4056
|
+
}
|
|
4057
|
+
function runTitleOf(run) {
|
|
4058
|
+
return firstString(run, ["title", "summary", "name"], taskIdOf(run) || "(untitled)");
|
|
4059
|
+
}
|
|
4060
|
+
function requestIdOf(entry) {
|
|
4061
|
+
return firstString(entry, ["requestId", "id", "approvalId", "inputId"], "(unknown-request)");
|
|
4062
|
+
}
|
|
4063
|
+
function shouldUseClackOutput() {
|
|
4064
|
+
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
4065
|
+
}
|
|
4066
|
+
function printFormattedOutput(message2, options = {}) {
|
|
4067
|
+
if (!shouldUseClackOutput()) {
|
|
4068
|
+
console.log(message2);
|
|
4069
|
+
return;
|
|
4070
|
+
}
|
|
4071
|
+
if (options.title)
|
|
4072
|
+
note3(message2, options.title);
|
|
4073
|
+
else
|
|
4074
|
+
log3.message(message2);
|
|
4075
|
+
}
|
|
4076
|
+
function formatStatusPill(status) {
|
|
4077
|
+
const label = status || "unknown";
|
|
4078
|
+
return statusColor(label)(`\u25CF ${label}`);
|
|
4079
|
+
}
|
|
4080
|
+
function formatSection(title, subtitle) {
|
|
4081
|
+
return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
4082
|
+
}
|
|
4083
|
+
function formatSuccessCard(title, rows = []) {
|
|
4084
|
+
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}`);
|
|
4085
|
+
return [formatSection(title), ...body].join(`
|
|
4086
|
+
`);
|
|
4087
|
+
}
|
|
4088
|
+
function formatNextSteps(steps) {
|
|
4089
|
+
if (steps.length === 0)
|
|
4090
|
+
return [];
|
|
4091
|
+
return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
|
|
4092
|
+
}
|
|
4093
|
+
function formatTaskList(tasks, options = {}) {
|
|
4094
|
+
if (options.raw)
|
|
4095
|
+
return tasks.map((task) => JSON.stringify(task)).join(`
|
|
4096
|
+
`);
|
|
4097
|
+
if (tasks.length === 0)
|
|
4098
|
+
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(`
|
|
4099
|
+
`);
|
|
4100
|
+
const rows = tasks.map((task) => {
|
|
4101
|
+
const raw = rawObject(task);
|
|
4102
|
+
const id = stringField(task, "id", "<unknown>");
|
|
4103
|
+
const status = stringField(task, "status", "unknown");
|
|
4104
|
+
const title = stringField(task, "title", "Untitled task");
|
|
4105
|
+
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
4106
|
+
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
4107
|
+
return { id, status, title, source, labels };
|
|
4108
|
+
});
|
|
4109
|
+
const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
|
|
4110
|
+
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
4111
|
+
const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
4112
|
+
const body = rows.map((row) => {
|
|
4113
|
+
const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
|
|
4114
|
+
const source = row.source ? pc3.dim(` ${row.source}`) : "";
|
|
4115
|
+
return [
|
|
4116
|
+
pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
|
|
4117
|
+
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
4118
|
+
`${row.title}${labels}${source}`
|
|
4119
|
+
].join(" ");
|
|
4120
|
+
});
|
|
4121
|
+
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(`
|
|
4122
|
+
`);
|
|
4123
|
+
}
|
|
4124
|
+
function formatTaskCard(task, options = {}) {
|
|
4125
|
+
const raw = rawObject(task);
|
|
4126
|
+
const id = stringField(task, "id", stringField(raw, "id", "<unknown>"));
|
|
4127
|
+
const status = stringField(task, "status", stringField(raw, "status", "unknown"));
|
|
4128
|
+
const title = stringField(task, "title", stringField(raw, "title", "Untitled task"));
|
|
4129
|
+
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
4130
|
+
const url = stringField(task, "url", stringField(raw, "url", ""));
|
|
4131
|
+
const number = numberField(task, "number") ?? numberField(raw, "number");
|
|
4132
|
+
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
4133
|
+
const assignees = arrayField(task, "assignees").length > 0 ? arrayField(task, "assignees") : arrayField(raw, "assignees");
|
|
4134
|
+
const readiness = compactValue(task.readiness ?? raw.readiness);
|
|
4135
|
+
const validators = compactValue(task.validators ?? raw.validators ?? task.validation ?? raw.validation);
|
|
4136
|
+
const rows = [
|
|
4137
|
+
["task", pc3.bold(id)],
|
|
4138
|
+
["status", formatStatusPill(status)],
|
|
4139
|
+
["title", title],
|
|
4140
|
+
["source", source],
|
|
4141
|
+
["number", number],
|
|
4142
|
+
["labels", labels.length ? labels.map((label) => `#${label}`).join(" ") : ""],
|
|
4143
|
+
["assignees", assignees.join(", ")],
|
|
4144
|
+
["readiness", readiness],
|
|
4145
|
+
["validators", validators],
|
|
4146
|
+
["url", url]
|
|
4147
|
+
];
|
|
4148
|
+
return [
|
|
4149
|
+
formatSuccessCard(options.title ?? (options.selected ? "Selected task" : "Task"), rows),
|
|
4150
|
+
"",
|
|
4151
|
+
...formatNextSteps([`Start: \`rig task run ${id}\``, `Details: \`rig task show ${id} --raw\``])
|
|
4152
|
+
].join(`
|
|
4153
|
+
`);
|
|
4154
|
+
}
|
|
4155
|
+
function formatTaskDetails(task) {
|
|
4156
|
+
return formatTaskCard(task, { title: "Task details" });
|
|
4157
|
+
}
|
|
4158
|
+
function formatRunList(runs, options = {}) {
|
|
4159
|
+
if (runs.length === 0) {
|
|
4160
|
+
return [
|
|
4161
|
+
formatSection("Runs", "none recorded"),
|
|
4162
|
+
options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
|
|
4163
|
+
"",
|
|
4164
|
+
...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
|
|
4165
|
+
].join(`
|
|
4166
|
+
`);
|
|
4167
|
+
}
|
|
4168
|
+
const rows = runs.map((run) => {
|
|
4169
|
+
const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
|
|
4170
|
+
const status = stringField(run, "status", "unknown");
|
|
4171
|
+
const taskId = stringField(run, "taskId", "");
|
|
4172
|
+
const title = stringField(run, "title", taskId || "(untitled)");
|
|
4173
|
+
const runtime = stringField(run, "runtimeAdapter", "");
|
|
4174
|
+
return { runId, status, title, runtime };
|
|
4175
|
+
});
|
|
4176
|
+
const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
|
|
4177
|
+
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
4178
|
+
const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
4179
|
+
const body = rows.map((row) => [
|
|
4180
|
+
pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
|
|
4181
|
+
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
4182
|
+
`${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
|
|
4183
|
+
].join(" "));
|
|
4184
|
+
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(`
|
|
4185
|
+
`);
|
|
4186
|
+
}
|
|
4187
|
+
function formatSubmittedRun(input) {
|
|
4188
|
+
const rows = [["run", pc3.bold(input.runId)]];
|
|
4189
|
+
if (input.task) {
|
|
4190
|
+
const id = stringField(input.task, "id", "<unknown>");
|
|
4191
|
+
const status = stringField(input.task, "status", "unknown");
|
|
4192
|
+
const title = stringField(input.task, "title", "Untitled task");
|
|
4193
|
+
rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
|
|
4194
|
+
}
|
|
4195
|
+
const runtime = [input.runtimeAdapter || "pi", input.runtimeMode || "full-access", input.interactionMode || "default"].filter(Boolean).join(" \xB7 ");
|
|
4196
|
+
rows.push(["runtime", runtime]);
|
|
4197
|
+
return [
|
|
4198
|
+
formatSuccessCard("Run submitted", rows),
|
|
4199
|
+
"",
|
|
4200
|
+
...formatNextSteps([
|
|
4201
|
+
`Attach: \`rig run attach ${input.runId} --follow\``,
|
|
4202
|
+
`Inspect: \`rig run show ${input.runId}\``,
|
|
4203
|
+
input.detached ? "Submitted detached; attach when you are ready." : "Interactive mode opens the native bundled Pi frontend."
|
|
4204
|
+
])
|
|
4205
|
+
].join(`
|
|
4206
|
+
`);
|
|
4207
|
+
}
|
|
4208
|
+
function formatRunCard(run, options = {}) {
|
|
4209
|
+
const raw = rawObject(run);
|
|
4210
|
+
const merged = { ...raw, ...run };
|
|
4211
|
+
const runId = runIdOf(merged);
|
|
4212
|
+
const status = firstString(merged, ["status"], "unknown");
|
|
4213
|
+
const taskId = taskIdOf(merged);
|
|
4214
|
+
const title = runTitleOf(merged);
|
|
4215
|
+
const runtime = firstString(merged, ["runtimeAdapter", "runtime", "adapter"]);
|
|
4216
|
+
const mode = firstString(merged, ["runtimeMode", "mode"]);
|
|
4217
|
+
const interaction = firstString(merged, ["interactionMode"]);
|
|
4218
|
+
const created = compactDate(firstString(merged, ["createdAt"]));
|
|
4219
|
+
const started = compactDate(firstString(merged, ["startedAt"]));
|
|
4220
|
+
const updated = compactDate(firstString(merged, ["updatedAt"]));
|
|
4221
|
+
const completed = compactDate(firstString(merged, ["completedAt", "finishedAt"]));
|
|
4222
|
+
const worktree = firstString(merged, ["worktreePath", "cwd", "projectRoot"]);
|
|
4223
|
+
const piSession = merged.piSession && typeof merged.piSession === "object" && !Array.isArray(merged.piSession) ? firstString(merged.piSession, ["sessionId", "id"]) : "";
|
|
4224
|
+
const timeline = Array.isArray(merged.timeline) ? merged.timeline.length : null;
|
|
4225
|
+
const approvals = Array.isArray(merged.approvals) ? merged.approvals.length : null;
|
|
4226
|
+
const inputs = Array.isArray(merged.userInputs) ? merged.userInputs.length : null;
|
|
4227
|
+
const rows = [
|
|
4228
|
+
["run", pc3.bold(runId)],
|
|
4229
|
+
["status", formatStatusPill(status)],
|
|
4230
|
+
["task", taskId],
|
|
4231
|
+
["title", title],
|
|
4232
|
+
["runtime", [runtime, mode, interaction].filter(Boolean).join(" \xB7 ")],
|
|
4233
|
+
["created", created],
|
|
4234
|
+
["started", started],
|
|
4235
|
+
["updated", updated],
|
|
4236
|
+
["completed", completed],
|
|
4237
|
+
["worktree", worktree],
|
|
4238
|
+
["pi", piSession],
|
|
4239
|
+
["timeline", timeline],
|
|
4240
|
+
["approvals", approvals],
|
|
4241
|
+
["inputs", inputs]
|
|
4242
|
+
];
|
|
4243
|
+
return [
|
|
4244
|
+
formatSuccessCard(options.title ?? "Run details", rows),
|
|
4245
|
+
"",
|
|
4246
|
+
...formatNextSteps([`Follow live: \`rig run attach ${runId} --follow\``, `Raw payload: \`rig run show ${runId} --raw\``])
|
|
4247
|
+
].join(`
|
|
4248
|
+
`);
|
|
4249
|
+
}
|
|
4250
|
+
function formatRunStatus(summary, options = {}) {
|
|
4251
|
+
const activeRuns = summary.activeRuns ?? [];
|
|
4252
|
+
const recentRuns = summary.recentRuns ?? [];
|
|
4253
|
+
const lines = [formatSection("Run status", options.source === "server" ? "selected server" : "local state")];
|
|
4254
|
+
lines.push("", pc3.bold(`Active runs (${activeRuns.length})`));
|
|
4255
|
+
if (activeRuns.length === 0) {
|
|
4256
|
+
lines.push(pc3.dim("No active runs."));
|
|
4257
|
+
} else {
|
|
4258
|
+
for (const run of activeRuns) {
|
|
4259
|
+
lines.push(formatRunSummaryLine(run));
|
|
4260
|
+
}
|
|
4261
|
+
}
|
|
4262
|
+
lines.push("", pc3.bold(`Recent runs (${recentRuns.length})`));
|
|
4263
|
+
if (recentRuns.length === 0) {
|
|
4264
|
+
lines.push(pc3.dim("No recent terminal runs."));
|
|
4265
|
+
} else {
|
|
4266
|
+
for (const run of recentRuns.slice(0, 10)) {
|
|
4267
|
+
lines.push(formatRunSummaryLine(run));
|
|
4268
|
+
}
|
|
4269
|
+
}
|
|
4270
|
+
lines.push("", ...formatNextSteps(["Start work: `rig task run --next`", "Attach: `rig run attach <run-id> --follow`", "Details: `rig run show <run-id>`"]));
|
|
4271
|
+
return lines.join(`
|
|
4272
|
+
`);
|
|
4273
|
+
}
|
|
4274
|
+
function formatRunSummaryLine(run) {
|
|
4275
|
+
const record = run;
|
|
4276
|
+
const runId = runIdOf(record);
|
|
4277
|
+
const status = firstString(record, ["status"], "unknown");
|
|
4278
|
+
const taskId = taskIdOf(record);
|
|
4279
|
+
const title = runTitleOf(record);
|
|
4280
|
+
const runtime = firstString(record, ["runtimeAdapter", "runtime", "adapter"]);
|
|
4281
|
+
const descriptor = [taskId, title].filter(Boolean).join(" \xB7 ");
|
|
4282
|
+
return `${pc3.dim("\u2502")} ${pc3.bold(runId)} ${formatStatusPill(status)} ${descriptor}${runtime ? pc3.dim(` ${runtime}`) : ""}`;
|
|
4283
|
+
}
|
|
4284
|
+
function formatInboxList(kind, entries) {
|
|
4285
|
+
const title = kind === "approvals" ? "Approval inbox" : "Input inbox";
|
|
4286
|
+
if (entries.length === 0) {
|
|
4287
|
+
return [
|
|
4288
|
+
formatSection(title, "empty"),
|
|
4289
|
+
pc3.dim(kind === "approvals" ? "No pending approvals." : "No pending user-input requests."),
|
|
4290
|
+
"",
|
|
4291
|
+
...formatNextSteps(["Check runs: `rig run status`", "Start work: `rig task run --next`"])
|
|
4292
|
+
].join(`
|
|
4293
|
+
`);
|
|
4294
|
+
}
|
|
4295
|
+
const lines = [formatSection(title, `${entries.length} pending`)];
|
|
4296
|
+
for (const entry of entries) {
|
|
4297
|
+
const record = entry.record && typeof entry.record === "object" && !Array.isArray(entry.record) ? entry.record : entry;
|
|
4298
|
+
const runId = firstString(entry, ["runId"], firstString(record, ["runId"]));
|
|
4299
|
+
const taskId = firstString(entry, ["taskId"], firstString(record, ["taskId", "task"]));
|
|
4300
|
+
const requestId = requestIdOf(record);
|
|
4301
|
+
const status = firstString(record, ["status", "state"], "pending");
|
|
4302
|
+
const prompt = firstString(record, ["prompt", "message", "reason", "title", "summary"], kind === "approvals" ? "Approval requested" : "Input requested");
|
|
4303
|
+
lines.push(`${pc3.dim("\u2502")} ${pc3.bold(requestId)} ${formatStatusPill(status)} ${prompt}`);
|
|
4304
|
+
lines.push(`${pc3.dim("\u2502")} ${pc3.dim("run ")} ${runId || "(unknown-run)"}${taskId ? pc3.dim(` task ${taskId}`) : ""}`);
|
|
4305
|
+
}
|
|
4306
|
+
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`"]));
|
|
4307
|
+
return lines.join(`
|
|
4308
|
+
`);
|
|
4309
|
+
}
|
|
4310
|
+
function formatConnectionList(connections) {
|
|
4311
|
+
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
4312
|
+
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
4313
|
+
const lines = rows.map(([alias, connection]) => [
|
|
4314
|
+
pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
4315
|
+
formatStatusPill(connection.kind),
|
|
4316
|
+
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
4317
|
+
].join(" "));
|
|
4318
|
+
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(`
|
|
4319
|
+
`);
|
|
4320
|
+
}
|
|
4321
|
+
function formatConnectionStatus(selected, connections) {
|
|
4322
|
+
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
4323
|
+
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
4324
|
+
return [
|
|
4325
|
+
formatSection("Rig server", "selected for this repo"),
|
|
4326
|
+
`${pc3.dim("\u2502")} ${pc3.dim("selected ")} ${pc3.bold(selected)}`,
|
|
4327
|
+
`${pc3.dim("\u2502")} ${pc3.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
4328
|
+
`${pc3.dim("\u2502")} ${pc3.dim("target ")} ${target ?? "not configured"}`,
|
|
4329
|
+
"",
|
|
4330
|
+
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
4331
|
+
].join(`
|
|
4332
|
+
`);
|
|
4333
|
+
}
|
|
4334
|
+
|
|
4335
|
+
// packages/cli/src/commands/inbox.ts
|
|
4336
|
+
function isRemoteConnectionSelected(projectRoot) {
|
|
4337
|
+
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
4338
|
+
}
|
|
4339
|
+
function runMatches(entry, filters) {
|
|
4340
|
+
const runId = typeof entry.runId === "string" ? entry.runId : typeof entry.id === "string" ? entry.id : "";
|
|
4341
|
+
const taskId = typeof entry.taskId === "string" ? entry.taskId : "";
|
|
4342
|
+
return (!filters.run || runId === filters.run) && (!filters.task || taskId === filters.task);
|
|
4343
|
+
}
|
|
4344
|
+
function normalizeRemoteRunDetails(payload) {
|
|
4345
|
+
const run = payload.run;
|
|
4346
|
+
if (run && typeof run === "object" && !Array.isArray(run)) {
|
|
4347
|
+
return {
|
|
4348
|
+
...run,
|
|
4349
|
+
...Array.isArray(payload.timeline) ? { timeline: payload.timeline } : {},
|
|
4350
|
+
...Array.isArray(payload.approvals) ? { approvals: payload.approvals } : {},
|
|
4351
|
+
...Array.isArray(payload.userInputs) ? { userInputs: payload.userInputs } : {}
|
|
4352
|
+
};
|
|
4353
|
+
}
|
|
4354
|
+
return payload;
|
|
4355
|
+
}
|
|
4356
|
+
function remoteRecordsFromRun(run, kind) {
|
|
4357
|
+
const key = kind === "approvals" ? "approvals" : "userInputs";
|
|
4358
|
+
const direct = run[key];
|
|
4359
|
+
if (!Array.isArray(direct))
|
|
4360
|
+
return [];
|
|
4361
|
+
const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
|
|
4362
|
+
const taskId = typeof run.taskId === "string" ? run.taskId : "";
|
|
4363
|
+
return direct.filter((record) => Boolean(record && typeof record === "object" && !Array.isArray(record))).map((record) => ({ runId, taskId, record }));
|
|
4364
|
+
}
|
|
4365
|
+
async function listRemoteInboxRecords(context, kind, filters) {
|
|
4366
|
+
const runs = (await listRunsViaServer(context, { limit: 100 })).filter((entry) => runMatches(entry, filters));
|
|
4367
|
+
const records = [];
|
|
4368
|
+
for (const run of runs) {
|
|
4369
|
+
const runId = typeof run.runId === "string" ? run.runId : typeof run.id === "string" ? run.id : "";
|
|
4370
|
+
const detailed = runId ? normalizeRemoteRunDetails(await getRunDetailsViaServer(context, runId).catch(() => run)) : run;
|
|
4371
|
+
records.push(...remoteRecordsFromRun(detailed, kind));
|
|
4372
|
+
}
|
|
4373
|
+
return records;
|
|
4374
|
+
}
|
|
4375
|
+
function listLocalInboxRecords(context, kind, filters) {
|
|
4376
|
+
const fileName = kind === "approvals" ? "approvals.jsonl" : "user-input.jsonl";
|
|
4377
|
+
const runs = listAuthorityRuns(context.projectRoot).filter((entry) => (!filters.run || entry.runId === filters.run) && (!filters.task || entry.taskId === filters.task));
|
|
4378
|
+
return runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), fileName)).map((record) => ({
|
|
4379
|
+
runId: entry.runId,
|
|
4380
|
+
taskId: entry.taskId ?? undefined,
|
|
4381
|
+
record
|
|
4382
|
+
})));
|
|
4383
|
+
}
|
|
4384
|
+
async function listInboxRecords(context, kind, filters) {
|
|
4385
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4386
|
+
return listRemoteInboxRecords(context, kind, filters);
|
|
4387
|
+
}
|
|
4388
|
+
return listLocalInboxRecords(context, kind, filters);
|
|
4389
|
+
}
|
|
3982
4390
|
async function executeInbox(context, args) {
|
|
3983
4391
|
const [command = "approvals", ...rest] = args;
|
|
3984
4392
|
switch (command) {
|
|
@@ -3988,16 +4396,10 @@ async function executeInbox(context, args) {
|
|
|
3988
4396
|
pending = run.rest;
|
|
3989
4397
|
const task = takeOption(pending, "--task");
|
|
3990
4398
|
pending = task.rest;
|
|
3991
|
-
requireNoExtraArgs(pending, "
|
|
3992
|
-
const
|
|
3993
|
-
const approvals = runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "approvals.jsonl")).map((record) => ({
|
|
3994
|
-
runId: entry.runId,
|
|
3995
|
-
record
|
|
3996
|
-
})));
|
|
4399
|
+
requireNoExtraArgs(pending, "rig inbox approvals [--run <id>] [--task <id>]");
|
|
4400
|
+
const approvals = await listInboxRecords(context, "approvals", { run: run.value, task: task.value });
|
|
3997
4401
|
if (context.outputMode === "text") {
|
|
3998
|
-
|
|
3999
|
-
console.log(JSON.stringify(approval));
|
|
4000
|
-
}
|
|
4402
|
+
printFormattedOutput(formatInboxList("approvals", approvals));
|
|
4001
4403
|
}
|
|
4002
4404
|
return { ok: true, group: "inbox", command, details: { approvals } };
|
|
4003
4405
|
}
|
|
@@ -4009,19 +4411,22 @@ async function executeInbox(context, args) {
|
|
|
4009
4411
|
pending = request.rest;
|
|
4010
4412
|
const decision = takeOption(pending, "--decision");
|
|
4011
4413
|
pending = decision.rest;
|
|
4012
|
-
const
|
|
4013
|
-
pending =
|
|
4014
|
-
requireNoExtraArgs(pending, "
|
|
4414
|
+
const note4 = takeOption(pending, "--note");
|
|
4415
|
+
pending = note4.rest;
|
|
4416
|
+
requireNoExtraArgs(pending, "rig inbox approve --run <id> --request <id> --decision approve|reject [--note <text>]");
|
|
4015
4417
|
if (!run.value || !request.value || !decision.value) {
|
|
4016
4418
|
throw new CliError2("approve requires --run, --request, and --decision.");
|
|
4017
4419
|
}
|
|
4018
4420
|
if (decision.value !== "approve" && decision.value !== "reject") {
|
|
4019
4421
|
throw new CliError2("decision must be approve or reject.");
|
|
4020
4422
|
}
|
|
4423
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4424
|
+
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);
|
|
4425
|
+
}
|
|
4021
4426
|
const approvalsPath = resolve13(resolveAuthorityRunDir2(context.projectRoot, run.value), "approvals.jsonl");
|
|
4022
4427
|
const approvals = readJsonlFile3(approvalsPath);
|
|
4023
4428
|
const resolvedAt = new Date().toISOString();
|
|
4024
|
-
const next = approvals.map((entry) => entry.requestId === request.value || entry.id === request.value ? { ...entry, status: "resolved", decision: decision.value, note:
|
|
4429
|
+
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);
|
|
4025
4430
|
writeFileSync4(approvalsPath, `${next.map((entry) => JSON.stringify(entry)).join(`
|
|
4026
4431
|
`)}
|
|
4027
4432
|
`, "utf8");
|
|
@@ -4033,16 +4438,10 @@ async function executeInbox(context, args) {
|
|
|
4033
4438
|
pending = run.rest;
|
|
4034
4439
|
const task = takeOption(pending, "--task");
|
|
4035
4440
|
pending = task.rest;
|
|
4036
|
-
requireNoExtraArgs(pending, "
|
|
4037
|
-
const
|
|
4038
|
-
const requests = runs.flatMap((entry) => readJsonlFile3(resolve13(resolveAuthorityRunDir2(context.projectRoot, entry.runId), "user-input.jsonl")).map((record) => ({
|
|
4039
|
-
runId: entry.runId,
|
|
4040
|
-
record
|
|
4041
|
-
})));
|
|
4441
|
+
requireNoExtraArgs(pending, "rig inbox inputs [--run <id>] [--task <id>]");
|
|
4442
|
+
const requests = await listInboxRecords(context, "inputs", { run: run.value, task: task.value });
|
|
4042
4443
|
if (context.outputMode === "text") {
|
|
4043
|
-
|
|
4044
|
-
console.log(JSON.stringify(request));
|
|
4045
|
-
}
|
|
4444
|
+
printFormattedOutput(formatInboxList("inputs", requests));
|
|
4046
4445
|
}
|
|
4047
4446
|
return { ok: true, group: "inbox", command, details: { requests } };
|
|
4048
4447
|
}
|
|
@@ -4069,10 +4468,13 @@ async function executeInbox(context, args) {
|
|
|
4069
4468
|
remaining.push(current);
|
|
4070
4469
|
}
|
|
4071
4470
|
}
|
|
4072
|
-
requireNoExtraArgs(remaining, "
|
|
4471
|
+
requireNoExtraArgs(remaining, "rig inbox respond --run <id> --request <id> --answer key=value [--answer key=value]");
|
|
4073
4472
|
if (!run.value || !request.value || answers.length === 0) {
|
|
4074
4473
|
throw new CliError2("respond requires --run, --request, and at least one --answer.");
|
|
4075
4474
|
}
|
|
4475
|
+
if (isRemoteConnectionSelected(context.projectRoot)) {
|
|
4476
|
+
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);
|
|
4477
|
+
}
|
|
4076
4478
|
const parsedAnswers = Object.fromEntries(answers.map((entry) => {
|
|
4077
4479
|
const [key, ...restValue] = entry.split("=");
|
|
4078
4480
|
return [key, restValue.join("=")];
|
|
@@ -4496,7 +4898,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4496
4898
|
const taskSourceKind = config?.taskSource?.kind;
|
|
4497
4899
|
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."));
|
|
4498
4900
|
const repo = readRepoConnection(projectRoot);
|
|
4499
|
-
checks.push(repo ? check("project-link", "repo selected Rig
|
|
4901
|
+
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>`."));
|
|
4500
4902
|
const selected = (() => {
|
|
4501
4903
|
try {
|
|
4502
4904
|
return resolveSelectedConnection(projectRoot);
|
|
@@ -4504,7 +4906,7 @@ async function runRigDoctorChecks(options) {
|
|
|
4504
4906
|
return null;
|
|
4505
4907
|
}
|
|
4506
4908
|
})();
|
|
4507
|
-
checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server
|
|
4909
|
+
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));
|
|
4508
4910
|
let server = null;
|
|
4509
4911
|
try {
|
|
4510
4912
|
server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
|
|
@@ -5313,179 +5715,24 @@ Usage: rig init`, 1);
|
|
|
5313
5715
|
|
|
5314
5716
|
// packages/cli/src/commands/connect.ts
|
|
5315
5717
|
import { cancel as cancel2, isCancel as isCancel2, select as select2 } from "@clack/prompts";
|
|
5316
|
-
|
|
5317
|
-
|
|
5318
|
-
import pc3 from "picocolors";
|
|
5319
|
-
function stringField(record, key, fallback = "") {
|
|
5320
|
-
const value = record[key];
|
|
5321
|
-
return typeof value === "string" && value.trim() ? value.trim() : fallback;
|
|
5322
|
-
}
|
|
5323
|
-
function arrayField(record, key) {
|
|
5324
|
-
const value = record[key];
|
|
5325
|
-
return Array.isArray(value) ? value.flatMap((entry) => typeof entry === "string" && entry.trim() ? [entry.trim()] : []) : [];
|
|
5718
|
+
function usageName(options) {
|
|
5719
|
+
return `rig ${options.group}`;
|
|
5326
5720
|
}
|
|
5327
|
-
function
|
|
5328
|
-
|
|
5329
|
-
|
|
5330
|
-
|
|
5331
|
-
|
|
5332
|
-
|
|
5333
|
-
|
|
5334
|
-
|
|
5335
|
-
|
|
5336
|
-
|
|
5337
|
-
}
|
|
5338
|
-
|
|
5339
|
-
|
|
5340
|
-
}
|
|
5341
|
-
|
|
5342
|
-
const normalized = status.toLowerCase();
|
|
5343
|
-
if (["completed", "merged", "closed", "done", "accepted", "pass", "selected"].includes(normalized))
|
|
5344
|
-
return pc3.green;
|
|
5345
|
-
if (["failed", "needs_attention", "needs-attention", "blocked", "error"].includes(normalized))
|
|
5346
|
-
return pc3.red;
|
|
5347
|
-
if (["running", "reviewing", "validating", "in_progress", "in-progress", "remote"].includes(normalized))
|
|
5348
|
-
return pc3.cyan;
|
|
5349
|
-
if (["ready", "open", "queued", "created", "preparing", "local"].includes(normalized))
|
|
5350
|
-
return pc3.yellow;
|
|
5351
|
-
return pc3.dim;
|
|
5352
|
-
}
|
|
5353
|
-
function formatStatusPill(status) {
|
|
5354
|
-
const label = status || "unknown";
|
|
5355
|
-
return statusColor(label)(`\u25CF ${label}`);
|
|
5356
|
-
}
|
|
5357
|
-
function formatSection(title, subtitle) {
|
|
5358
|
-
return `${pc3.bold(pc3.cyan("\u25C6"))} ${pc3.bold(title)}${subtitle ? pc3.dim(` \u2014 ${subtitle}`) : ""}`;
|
|
5359
|
-
}
|
|
5360
|
-
function formatSuccessCard(title, rows = []) {
|
|
5361
|
-
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}`);
|
|
5362
|
-
return [formatSection(title), ...body].join(`
|
|
5363
|
-
`);
|
|
5364
|
-
}
|
|
5365
|
-
function formatNextSteps(steps) {
|
|
5366
|
-
if (steps.length === 0)
|
|
5367
|
-
return [];
|
|
5368
|
-
return [pc3.bold("Next"), ...steps.map((step) => `${pc3.dim("\u203A")} ${step}`)];
|
|
5369
|
-
}
|
|
5370
|
-
function formatTaskList(tasks, options = {}) {
|
|
5371
|
-
if (options.raw)
|
|
5372
|
-
return tasks.map((task) => JSON.stringify(task)).join(`
|
|
5373
|
-
`);
|
|
5374
|
-
if (tasks.length === 0)
|
|
5375
|
-
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(`
|
|
5376
|
-
`);
|
|
5377
|
-
const rows = tasks.map((task) => {
|
|
5378
|
-
const raw = rawObject(task);
|
|
5379
|
-
const id = stringField(task, "id", "<unknown>");
|
|
5380
|
-
const status = stringField(task, "status", "unknown");
|
|
5381
|
-
const title = stringField(task, "title", "Untitled task");
|
|
5382
|
-
const source = stringField(task, "source", stringField(raw, "source", ""));
|
|
5383
|
-
const labels = arrayField(task, "labels").length > 0 ? arrayField(task, "labels") : arrayField(raw, "labels");
|
|
5384
|
-
return { id, status, title, source, labels };
|
|
5385
|
-
});
|
|
5386
|
-
const idWidth = Math.min(18, Math.max(4, ...rows.map((row) => row.id.length)));
|
|
5387
|
-
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
5388
|
-
const header = `${pc3.bold(pad("TASK", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
5389
|
-
const body = rows.map((row) => {
|
|
5390
|
-
const labels = row.labels.length > 0 ? pc3.dim(` ${row.labels.slice(0, 4).map((label) => `#${label}`).join(" ")}`) : "";
|
|
5391
|
-
const source = row.source ? pc3.dim(` ${row.source}`) : "";
|
|
5392
|
-
return [
|
|
5393
|
-
pc3.bold(pad(truncate(row.id, idWidth), idWidth)),
|
|
5394
|
-
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
5395
|
-
`${row.title}${labels}${source}`
|
|
5396
|
-
].join(" ");
|
|
5397
|
-
});
|
|
5398
|
-
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(`
|
|
5399
|
-
`);
|
|
5400
|
-
}
|
|
5401
|
-
function formatRunList(runs, options = {}) {
|
|
5402
|
-
if (runs.length === 0) {
|
|
5403
|
-
return [
|
|
5404
|
-
formatSection("Runs", "none recorded"),
|
|
5405
|
-
options.source === "server" ? pc3.dim("No runs recorded on the selected Rig server.") : pc3.dim("No runs recorded in .rig/runs."),
|
|
5406
|
-
"",
|
|
5407
|
-
...formatNextSteps(["Start one: `rig task run --next`", "Check server: `rig server status`"])
|
|
5408
|
-
].join(`
|
|
5409
|
-
`);
|
|
5410
|
-
}
|
|
5411
|
-
const rows = runs.map((run) => {
|
|
5412
|
-
const runId = stringField(run, "runId", stringField(run, "id", "(unknown-run)"));
|
|
5413
|
-
const status = stringField(run, "status", "unknown");
|
|
5414
|
-
const taskId = stringField(run, "taskId", "");
|
|
5415
|
-
const title = stringField(run, "title", taskId || "(untitled)");
|
|
5416
|
-
const runtime = stringField(run, "runtimeAdapter", "");
|
|
5417
|
-
return { runId, status, title, runtime };
|
|
5418
|
-
});
|
|
5419
|
-
const idWidth = Math.min(36, Math.max(6, ...rows.map((row) => row.runId.length)));
|
|
5420
|
-
const statusWidth = Math.min(16, Math.max(6, ...rows.map((row) => row.status.length)));
|
|
5421
|
-
const header = `${pc3.bold(pad("RUN", idWidth))} ${pc3.bold(pad("STATUS", statusWidth))} ${pc3.bold("TITLE")}`;
|
|
5422
|
-
const body = rows.map((row) => [
|
|
5423
|
-
pc3.bold(pad(truncate(row.runId, idWidth), idWidth)),
|
|
5424
|
-
statusColor(row.status)(pad(truncate(row.status, statusWidth), statusWidth)),
|
|
5425
|
-
`${row.title}${row.runtime ? pc3.dim(` ${row.runtime}`) : ""}`
|
|
5426
|
-
].join(" "));
|
|
5427
|
-
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(`
|
|
5428
|
-
`);
|
|
5429
|
-
}
|
|
5430
|
-
function formatSubmittedRun(input) {
|
|
5431
|
-
const rows = [["run", pc3.bold(input.runId)]];
|
|
5432
|
-
if (input.task) {
|
|
5433
|
-
const id = stringField(input.task, "id", "<unknown>");
|
|
5434
|
-
const status = stringField(input.task, "status", "unknown");
|
|
5435
|
-
const title = stringField(input.task, "title", "Untitled task");
|
|
5436
|
-
rows.push(["task", `${pc3.bold(id)} ${formatStatusPill(status)} ${title}`]);
|
|
5437
|
-
}
|
|
5438
|
-
return [
|
|
5439
|
-
formatSuccessCard("Run submitted", rows),
|
|
5440
|
-
"",
|
|
5441
|
-
...formatNextSteps([`Attach: \`rig run attach ${input.runId} --follow\``, `Inspect: \`rig run show --run ${input.runId}\``])
|
|
5442
|
-
].join(`
|
|
5443
|
-
`);
|
|
5444
|
-
}
|
|
5445
|
-
function formatConnectionList(connections) {
|
|
5446
|
-
const rows = [["local", { kind: "local", mode: "auto" }], ...Object.entries(connections)];
|
|
5447
|
-
const aliasWidth = Math.min(24, Math.max(5, ...rows.map(([alias]) => alias.length)));
|
|
5448
|
-
const lines = rows.map(([alias, connection]) => [
|
|
5449
|
-
pc3.bold(pad(truncate(alias, aliasWidth), aliasWidth)),
|
|
5450
|
-
formatStatusPill(connection.kind),
|
|
5451
|
-
connection.kind === "remote" ? connection.baseUrl ?? "" : connection.mode ?? "local"
|
|
5452
|
-
].join(" "));
|
|
5453
|
-
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(`
|
|
5454
|
-
`);
|
|
5455
|
-
}
|
|
5456
|
-
function formatConnectionStatus(selected, connections) {
|
|
5457
|
-
const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
|
|
5458
|
-
const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
|
|
5459
|
-
return [
|
|
5460
|
-
formatSection("Rig server", "selected for this repo"),
|
|
5461
|
-
`${pc3.dim("\u2502")} ${pc3.dim("selected ")} ${pc3.bold(selected)}`,
|
|
5462
|
-
`${pc3.dim("\u2502")} ${pc3.dim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
|
|
5463
|
-
`${pc3.dim("\u2502")} ${pc3.dim("target ")} ${target ?? "not configured"}`,
|
|
5464
|
-
"",
|
|
5465
|
-
...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
|
|
5466
|
-
].join(`
|
|
5467
|
-
`);
|
|
5468
|
-
}
|
|
5469
|
-
|
|
5470
|
-
// packages/cli/src/commands/connect.ts
|
|
5471
|
-
function usageName(options) {
|
|
5472
|
-
return `rig ${options.group}`;
|
|
5473
|
-
}
|
|
5474
|
-
function parseConnection(alias, value, options) {
|
|
5475
|
-
if (alias === "local" && !value)
|
|
5476
|
-
return { kind: "local", mode: "auto" };
|
|
5477
|
-
if (!value)
|
|
5478
|
-
throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
|
|
5479
|
-
let parsed;
|
|
5480
|
-
try {
|
|
5481
|
-
parsed = new URL(value);
|
|
5482
|
-
} catch {
|
|
5483
|
-
throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
|
|
5484
|
-
}
|
|
5485
|
-
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
5486
|
-
throw new CliError2("Rig remote server URL must be http(s).", 1);
|
|
5487
|
-
}
|
|
5488
|
-
return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
|
|
5721
|
+
function parseConnection(alias, value, options) {
|
|
5722
|
+
if (alias === "local" && !value)
|
|
5723
|
+
return { kind: "local", mode: "auto" };
|
|
5724
|
+
if (!value)
|
|
5725
|
+
throw new CliError2(`Missing remote server URL. Usage: ${usageName(options)} add <alias> <url>`, 1);
|
|
5726
|
+
let parsed;
|
|
5727
|
+
try {
|
|
5728
|
+
parsed = new URL(value);
|
|
5729
|
+
} catch {
|
|
5730
|
+
throw new CliError2(`Invalid Rig server URL: ${value}`, 1);
|
|
5731
|
+
}
|
|
5732
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
5733
|
+
throw new CliError2("Rig remote server URL must be http(s).", 1);
|
|
5734
|
+
}
|
|
5735
|
+
return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
|
|
5489
5736
|
}
|
|
5490
5737
|
function printJsonOrText(context, payload, text2) {
|
|
5491
5738
|
if (context.outputMode === "json") {
|
|
@@ -5892,8 +6139,8 @@ async function executeInspect(context, args) {
|
|
|
5892
6139
|
switch (command) {
|
|
5893
6140
|
case "logs": {
|
|
5894
6141
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5895
|
-
requireNoExtraArgs(remaining, "
|
|
5896
|
-
const requiredTask = requireTask(task, "
|
|
6142
|
+
requireNoExtraArgs(remaining, "rig inspect logs --task <task-id>");
|
|
6143
|
+
const requiredTask = requireTask(task, "rig inspect logs --task <task-id>");
|
|
5897
6144
|
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];
|
|
5898
6145
|
if (!latestRun) {
|
|
5899
6146
|
throw new CliError2(`No runs found for ${requiredTask}.`);
|
|
@@ -5907,8 +6154,8 @@ async function executeInspect(context, args) {
|
|
|
5907
6154
|
}
|
|
5908
6155
|
case "artifacts": {
|
|
5909
6156
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5910
|
-
requireNoExtraArgs(remaining, "
|
|
5911
|
-
const requiredTask = requireTask(task, "
|
|
6157
|
+
requireNoExtraArgs(remaining, "rig inspect artifacts --task <task-id>");
|
|
6158
|
+
const requiredTask = requireTask(task, "rig inspect artifacts --task <task-id>");
|
|
5912
6159
|
const artifactRoot = resolveTaskArtifactDirs(context.projectRoot, requiredTask).find((path) => existsSync11(path));
|
|
5913
6160
|
if (!artifactRoot) {
|
|
5914
6161
|
throw new CliError2(`No artifacts found for ${requiredTask}.`);
|
|
@@ -5922,8 +6169,8 @@ async function executeInspect(context, args) {
|
|
|
5922
6169
|
previewPending = task.rest;
|
|
5923
6170
|
const file = takeOption(previewPending, "--file");
|
|
5924
6171
|
previewPending = file.rest;
|
|
5925
|
-
requireNoExtraArgs(previewPending, "
|
|
5926
|
-
const requiredTask = requireTask(task.value, "
|
|
6172
|
+
requireNoExtraArgs(previewPending, "rig inspect artifact --task <task-id> --file <name>");
|
|
6173
|
+
const requiredTask = requireTask(task.value, "rig inspect artifact --task <task-id> --file <name>");
|
|
5927
6174
|
if (!file.value) {
|
|
5928
6175
|
throw new CliError2("Missing --file for rig inspect artifact.");
|
|
5929
6176
|
}
|
|
@@ -5952,7 +6199,7 @@ async function executeInspect(context, args) {
|
|
|
5952
6199
|
}
|
|
5953
6200
|
case "diff": {
|
|
5954
6201
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
5955
|
-
requireNoExtraArgs(remaining, "
|
|
6202
|
+
requireNoExtraArgs(remaining, "rig inspect diff [--task <task-id>]");
|
|
5956
6203
|
if (task) {
|
|
5957
6204
|
const files = changedFilesForTask(context.projectRoot, task, false);
|
|
5958
6205
|
for (const file of files) {
|
|
@@ -5964,7 +6211,7 @@ async function executeInspect(context, args) {
|
|
|
5964
6211
|
return { ok: true, group: "inspect", command, details: { task: task || null } };
|
|
5965
6212
|
}
|
|
5966
6213
|
case "failures": {
|
|
5967
|
-
requireNoExtraArgs(rest, "
|
|
6214
|
+
requireNoExtraArgs(rest, "rig inspect failures");
|
|
5968
6215
|
const failed = resolveHarnessPaths2(context.projectRoot).failedApproachesPath;
|
|
5969
6216
|
if (!existsSync11(failed)) {
|
|
5970
6217
|
console.log("No failures recorded.");
|
|
@@ -5974,7 +6221,7 @@ async function executeInspect(context, args) {
|
|
|
5974
6221
|
return { ok: true, group: "inspect", command };
|
|
5975
6222
|
}
|
|
5976
6223
|
case "graph":
|
|
5977
|
-
requireNoExtraArgs(rest, "
|
|
6224
|
+
requireNoExtraArgs(rest, "rig inspect graph");
|
|
5978
6225
|
{
|
|
5979
6226
|
const monorepoRoot = resolveMonorepoRoot2(context.projectRoot);
|
|
5980
6227
|
const result = runCapture3(["br", "--no-db", "list", "--pretty"], monorepoRoot);
|
|
@@ -5985,7 +6232,7 @@ async function executeInspect(context, args) {
|
|
|
5985
6232
|
}
|
|
5986
6233
|
return { ok: true, group: "inspect", command };
|
|
5987
6234
|
case "audit": {
|
|
5988
|
-
requireNoExtraArgs(rest, "
|
|
6235
|
+
requireNoExtraArgs(rest, "rig inspect audit");
|
|
5989
6236
|
const auditPath = resolve19(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
|
|
5990
6237
|
if (!existsSync11(auditPath)) {
|
|
5991
6238
|
console.log("No audit log found.");
|
|
@@ -6044,7 +6291,7 @@ async function executeInspector(context, args) {
|
|
|
6044
6291
|
pending = secondsResult.rest;
|
|
6045
6292
|
const pollMsResult = takeOption(pending, "--poll-ms");
|
|
6046
6293
|
pending = pollMsResult.rest;
|
|
6047
|
-
requireNoExtraArgs(pending, "
|
|
6294
|
+
requireNoExtraArgs(pending, "rig inspector stream [--once] [--seconds <n>] [--poll-ms <n>]");
|
|
6048
6295
|
const seconds = secondsResult.value ? parseRequiredPositiveInt(secondsResult.value, "--seconds") : null;
|
|
6049
6296
|
const pollMs = pollMsResult.value ? parseRequiredPositiveInt(pollMsResult.value, "--poll-ms") : null;
|
|
6050
6297
|
if (context.outputMode === "json" && !onceResult.value && !seconds) {
|
|
@@ -6138,7 +6385,7 @@ async function executeInspector(context, args) {
|
|
|
6138
6385
|
let pending = rest;
|
|
6139
6386
|
const scanIdResult = takeOption(pending, "--scan-id");
|
|
6140
6387
|
pending = scanIdResult.rest;
|
|
6141
|
-
requireNoExtraArgs(pending, "
|
|
6388
|
+
requireNoExtraArgs(pending, "rig inspector scan-upstream-drift [--scan-id <id>]");
|
|
6142
6389
|
const connection = await ensureLocalRigServerConnection2(context.projectRoot);
|
|
6143
6390
|
const response = await fetch(new URL("/api/inspector/tools/invoke", connection.baseUrl), {
|
|
6144
6391
|
method: "POST",
|
|
@@ -6249,7 +6496,7 @@ async function executeRemote(context, args) {
|
|
|
6249
6496
|
const [subcommand = "list", ...subRest] = rest;
|
|
6250
6497
|
switch (subcommand) {
|
|
6251
6498
|
case "list": {
|
|
6252
|
-
requireNoExtraArgs(subRest, "
|
|
6499
|
+
requireNoExtraArgs(subRest, "rig remote endpoint list");
|
|
6253
6500
|
const endpoints = listManagedRemoteEndpoints(undefined, context.projectRoot);
|
|
6254
6501
|
const redactedEndpoints = endpoints.map((endpoint2) => redactRemoteEndpoint(endpoint2));
|
|
6255
6502
|
if (context.outputMode === "text") {
|
|
@@ -6273,7 +6520,7 @@ async function executeRemote(context, args) {
|
|
|
6273
6520
|
pending2 = port.rest;
|
|
6274
6521
|
const token = takeOption(pending2, "--token");
|
|
6275
6522
|
pending2 = token.rest;
|
|
6276
|
-
requireNoExtraArgs(pending2, "
|
|
6523
|
+
requireNoExtraArgs(pending2, "rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
|
|
6277
6524
|
if (!alias.value || !host.value || !token.value || !port.value) {
|
|
6278
6525
|
throw new CliError2("remote endpoint add requires --alias, --host, --port, and --token.");
|
|
6279
6526
|
}
|
|
@@ -6300,7 +6547,7 @@ async function executeRemote(context, args) {
|
|
|
6300
6547
|
pending2 = port.rest;
|
|
6301
6548
|
const token = takeOption(pending2, "--token");
|
|
6302
6549
|
pending2 = token.rest;
|
|
6303
|
-
requireNoExtraArgs(pending2, "
|
|
6550
|
+
requireNoExtraArgs(pending2, "rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
|
|
6304
6551
|
if (!endpointId.value && !alias.value) {
|
|
6305
6552
|
throw new CliError2("remote endpoint update requires --id <id> or --alias <a>.");
|
|
6306
6553
|
}
|
|
@@ -6323,7 +6570,7 @@ async function executeRemote(context, args) {
|
|
|
6323
6570
|
let pending2 = subRest;
|
|
6324
6571
|
const alias = takeOption(pending2, "--alias");
|
|
6325
6572
|
pending2 = alias.rest;
|
|
6326
|
-
requireNoExtraArgs(pending2, "
|
|
6573
|
+
requireNoExtraArgs(pending2, "rig remote endpoint remove --alias <a>");
|
|
6327
6574
|
if (!alias.value) {
|
|
6328
6575
|
throw new CliError2("remote endpoint remove requires --alias.");
|
|
6329
6576
|
}
|
|
@@ -6340,7 +6587,7 @@ async function executeRemote(context, args) {
|
|
|
6340
6587
|
let pending2 = subRest;
|
|
6341
6588
|
const alias = takeOption(pending2, "--alias");
|
|
6342
6589
|
pending2 = alias.rest;
|
|
6343
|
-
requireNoExtraArgs(pending2, "
|
|
6590
|
+
requireNoExtraArgs(pending2, "rig remote endpoint test --alias <a>");
|
|
6344
6591
|
if (!alias.value) {
|
|
6345
6592
|
throw new CliError2("remote endpoint test requires --alias.");
|
|
6346
6593
|
}
|
|
@@ -6371,7 +6618,7 @@ async function executeRemote(context, args) {
|
|
|
6371
6618
|
}
|
|
6372
6619
|
}
|
|
6373
6620
|
case "migrate": {
|
|
6374
|
-
requireNoExtraArgs(subRest, "
|
|
6621
|
+
requireNoExtraArgs(subRest, "rig remote endpoint migrate");
|
|
6375
6622
|
const result = migrateManagedRemoteEndpoints(context.projectRoot);
|
|
6376
6623
|
if (context.outputMode === "text") {
|
|
6377
6624
|
console.log(`Imported ${result.imported} endpoint(s) from ${result.sourcePath}${result.skipped > 0 ? `, skipped ${result.skipped}` : ""}.`);
|
|
@@ -6379,7 +6626,7 @@ async function executeRemote(context, args) {
|
|
|
6379
6626
|
return { ok: true, group: "remote", command: "endpoint migrate", details: result };
|
|
6380
6627
|
}
|
|
6381
6628
|
case "doctor": {
|
|
6382
|
-
requireNoExtraArgs(subRest, "
|
|
6629
|
+
requireNoExtraArgs(subRest, "rig remote endpoint doctor");
|
|
6383
6630
|
const result = doctorManagedRemoteEndpoints(context.projectRoot);
|
|
6384
6631
|
if (context.outputMode === "text") {
|
|
6385
6632
|
console.log(JSON.stringify(result, null, 2));
|
|
@@ -6432,17 +6679,17 @@ async function executeRemote(context, args) {
|
|
|
6432
6679
|
try {
|
|
6433
6680
|
switch (command) {
|
|
6434
6681
|
case "test": {
|
|
6435
|
-
requireNoExtraArgs(pending, "
|
|
6682
|
+
requireNoExtraArgs(pending, "rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6436
6683
|
const response = await withClient((client) => client.ping());
|
|
6437
6684
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6438
6685
|
}
|
|
6439
6686
|
case "status": {
|
|
6440
|
-
requireNoExtraArgs(pending, "
|
|
6687
|
+
requireNoExtraArgs(pending, "rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6441
6688
|
const response = await withClient((client) => client.getState());
|
|
6442
6689
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6443
6690
|
}
|
|
6444
6691
|
case "tasks": {
|
|
6445
|
-
requireNoExtraArgs(pending, "
|
|
6692
|
+
requireNoExtraArgs(pending, "rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6446
6693
|
const response = await withClient((client) => client.getTasks());
|
|
6447
6694
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
6448
6695
|
}
|
|
@@ -6452,7 +6699,7 @@ async function executeRemote(context, args) {
|
|
|
6452
6699
|
watchPending = secondsResult.rest;
|
|
6453
6700
|
const eventResult = takeOption(watchPending, "--event");
|
|
6454
6701
|
watchPending = eventResult.rest;
|
|
6455
|
-
requireNoExtraArgs(watchPending, "
|
|
6702
|
+
requireNoExtraArgs(watchPending, "rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
|
|
6456
6703
|
const seconds = parseOptionalPositiveInt(secondsResult.value, "--seconds");
|
|
6457
6704
|
const eventFilter = eventResult.value || undefined;
|
|
6458
6705
|
if (context.outputMode === "json" && !seconds) {
|
|
@@ -6521,7 +6768,7 @@ async function executeRemote(context, args) {
|
|
|
6521
6768
|
case "stop":
|
|
6522
6769
|
case "continue":
|
|
6523
6770
|
case "refresh": {
|
|
6524
|
-
requireNoExtraArgs(pending, `
|
|
6771
|
+
requireNoExtraArgs(pending, `rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6525
6772
|
const response = await withClient(async (client) => {
|
|
6526
6773
|
switch (command) {
|
|
6527
6774
|
case "pause":
|
|
@@ -6544,7 +6791,7 @@ async function executeRemote(context, args) {
|
|
|
6544
6791
|
let countPending = pending;
|
|
6545
6792
|
const countResult = takeOption(countPending, "--count");
|
|
6546
6793
|
countPending = countResult.rest;
|
|
6547
|
-
requireNoExtraArgs(countPending, `
|
|
6794
|
+
requireNoExtraArgs(countPending, `rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6548
6795
|
const count = parseRequiredPositiveInt(countResult.value, "--count");
|
|
6549
6796
|
const response = await withClient(async (client) => command === "add-iterations" ? await client.addIterations(count) : await client.removeIterations(count));
|
|
6550
6797
|
assertRemoteOperationSuccess(command, response);
|
|
@@ -6555,8 +6802,8 @@ async function executeRemote(context, args) {
|
|
|
6555
6802
|
let taskPending = pending;
|
|
6556
6803
|
const taskResult = takeOption(taskPending, "--task");
|
|
6557
6804
|
taskPending = taskResult.rest;
|
|
6558
|
-
requireNoExtraArgs(taskPending, `
|
|
6559
|
-
const taskId = requireTask(taskResult.value, `
|
|
6805
|
+
requireNoExtraArgs(taskPending, `rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6806
|
+
const taskId = requireTask(taskResult.value, `rig remote ${command} --task <id>`);
|
|
6560
6807
|
const response = await withClient(async (client) => command === "prompt-preview" ? await client.getPromptPreview(taskId) : await client.getIterationOutput(taskId));
|
|
6561
6808
|
assertRemoteOperationSuccess(command, response);
|
|
6562
6809
|
return { ok: true, group: "remote", command, details: toDetails(response) };
|
|
@@ -6569,7 +6816,7 @@ async function executeRemote(context, args) {
|
|
|
6569
6816
|
orchestrationPending = maxIterationsResult.rest;
|
|
6570
6817
|
const directMergeResult = takeFlag(orchestrationPending, "--direct-merge");
|
|
6571
6818
|
orchestrationPending = directMergeResult.rest;
|
|
6572
|
-
requireNoExtraArgs(orchestrationPending, "
|
|
6819
|
+
requireNoExtraArgs(orchestrationPending, "rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
|
|
6573
6820
|
const response = await withClient((client) => client.startOrchestration({
|
|
6574
6821
|
maxWorkers: parseOptionalPositiveInt(maxWorkersResult.value, "--max-workers"),
|
|
6575
6822
|
maxIterations: parseOptionalPositiveInt(maxIterationsResult.value, "--max-iterations"),
|
|
@@ -6590,8 +6837,8 @@ async function executeRemote(context, args) {
|
|
|
6590
6837
|
let orchestrationPending = pending;
|
|
6591
6838
|
const idResult = takeOption(orchestrationPending, "--id");
|
|
6592
6839
|
orchestrationPending = idResult.rest;
|
|
6593
|
-
requireNoExtraArgs(orchestrationPending, `
|
|
6594
|
-
const orchestrationId = requireTask(idResult.value, `
|
|
6840
|
+
requireNoExtraArgs(orchestrationPending, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6841
|
+
const orchestrationId = requireTask(idResult.value, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
|
|
6595
6842
|
const response = await withClient(async (client) => {
|
|
6596
6843
|
switch (command) {
|
|
6597
6844
|
case "orchestrate-pause":
|
|
@@ -6655,8 +6902,8 @@ var CANONICAL_STAGES = [
|
|
|
6655
6902
|
"Merge",
|
|
6656
6903
|
"Complete"
|
|
6657
6904
|
];
|
|
6658
|
-
function logDetail(
|
|
6659
|
-
return typeof
|
|
6905
|
+
function logDetail(log4) {
|
|
6906
|
+
return typeof log4.detail === "string" ? log4.detail.trim() : "";
|
|
6660
6907
|
}
|
|
6661
6908
|
function parseProviderProtocolLog(title, detail) {
|
|
6662
6909
|
if (title.trim().toLowerCase() !== "agent output")
|
|
@@ -6703,12 +6950,12 @@ function renderOperatorSnapshot(snapshot) {
|
|
|
6703
6950
|
const status = String(run.status ?? "unknown");
|
|
6704
6951
|
const logs = snapshot.logs ?? [];
|
|
6705
6952
|
const latestByStage = new Map;
|
|
6706
|
-
for (const
|
|
6707
|
-
const title = String(
|
|
6708
|
-
const stageName = String(
|
|
6953
|
+
for (const log4 of logs) {
|
|
6954
|
+
const title = String(log4.title ?? "").toLowerCase();
|
|
6955
|
+
const stageName = String(log4.stage ?? "").toLowerCase();
|
|
6709
6956
|
const stage = CANONICAL_STAGES.find((candidate) => candidate.toLowerCase() === title || candidate.toLowerCase() === stageName);
|
|
6710
6957
|
if (stage)
|
|
6711
|
-
latestByStage.set(stage,
|
|
6958
|
+
latestByStage.set(stage, log4);
|
|
6712
6959
|
}
|
|
6713
6960
|
const stageLines = CANONICAL_STAGES.flatMap((stage) => {
|
|
6714
6961
|
const match = latestByStage.get(stage);
|
|
@@ -7512,7 +7759,7 @@ async function attachRunOperatorView(context, input) {
|
|
|
7512
7759
|
}
|
|
7513
7760
|
|
|
7514
7761
|
// packages/cli/src/commands/run.ts
|
|
7515
|
-
function
|
|
7762
|
+
function normalizeRemoteRunDetails2(payload) {
|
|
7516
7763
|
const run = payload.run;
|
|
7517
7764
|
if (!run || typeof run !== "object" || Array.isArray(run))
|
|
7518
7765
|
return null;
|
|
@@ -7524,11 +7771,11 @@ function normalizeRemoteRunDetails(payload) {
|
|
|
7524
7771
|
};
|
|
7525
7772
|
}
|
|
7526
7773
|
var REMOTE_TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged"]);
|
|
7527
|
-
function
|
|
7774
|
+
function isRemoteConnectionSelected2(projectRoot) {
|
|
7528
7775
|
return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
|
|
7529
7776
|
}
|
|
7530
7777
|
async function listRunsForSelectedConnection(context, options = {}) {
|
|
7531
|
-
if (
|
|
7778
|
+
if (isRemoteConnectionSelected2(context.projectRoot)) {
|
|
7532
7779
|
return { runs: await listRunsViaServer(context, options), source: "server" };
|
|
7533
7780
|
}
|
|
7534
7781
|
return { runs: listAuthorityRuns3(context.projectRoot), source: "local" };
|
|
@@ -7537,9 +7784,6 @@ function runStringField(run, key, fallback = "") {
|
|
|
7537
7784
|
const value = run[key];
|
|
7538
7785
|
return typeof value === "string" && value.trim() ? value : fallback;
|
|
7539
7786
|
}
|
|
7540
|
-
function runDisplayTitle(run) {
|
|
7541
|
-
return runStringField(run, "title", runStringField(run, "taskId", "(untitled)"));
|
|
7542
|
-
}
|
|
7543
7787
|
function buildServerRunStatus(runs) {
|
|
7544
7788
|
const activeRuns = runs.filter((run) => !REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
7545
7789
|
const recentRuns = runs.filter((run) => REMOTE_TERMINAL_RUN_STATUSES.has(runStringField(run, "status").toLowerCase()));
|
|
@@ -7609,10 +7853,10 @@ async function executeRun(context, args) {
|
|
|
7609
7853
|
const runtimeContext = loadRuntimeContextFromEnv2() ?? undefined;
|
|
7610
7854
|
switch (command) {
|
|
7611
7855
|
case "list": {
|
|
7612
|
-
requireNoExtraArgs(rest, "
|
|
7856
|
+
requireNoExtraArgs(rest, "rig run list");
|
|
7613
7857
|
const { runs, source } = await listRunsForSelectedConnection(context, { limit: 100 });
|
|
7614
7858
|
if (context.outputMode === "text") {
|
|
7615
|
-
|
|
7859
|
+
printFormattedOutput(formatRunList(runs, { source }));
|
|
7616
7860
|
}
|
|
7617
7861
|
return { ok: true, group: "run", command, details: { runs, source } };
|
|
7618
7862
|
}
|
|
@@ -7622,7 +7866,7 @@ async function executeRun(context, args) {
|
|
|
7622
7866
|
pending = run.rest;
|
|
7623
7867
|
const purgeArtifacts = takeFlag(pending, "--purge-artifacts");
|
|
7624
7868
|
pending = purgeArtifacts.rest;
|
|
7625
|
-
requireNoExtraArgs(pending, "
|
|
7869
|
+
requireNoExtraArgs(pending, "rig run delete --run <id> [--purge-artifacts]");
|
|
7626
7870
|
if (!run.value) {
|
|
7627
7871
|
throw new CliError2("run delete requires --run <id>.");
|
|
7628
7872
|
}
|
|
@@ -7652,7 +7896,7 @@ async function executeRun(context, args) {
|
|
|
7652
7896
|
pending = keepRuntimes.rest;
|
|
7653
7897
|
const keepQueue = takeFlag(pending, "--keep-queue");
|
|
7654
7898
|
pending = keepQueue.rest;
|
|
7655
|
-
requireNoExtraArgs(pending, "
|
|
7899
|
+
requireNoExtraArgs(pending, "rig run cleanup --all [--keep-artifacts] [--keep-runtimes] [--keep-queue]");
|
|
7656
7900
|
if (!all.value) {
|
|
7657
7901
|
throw new CliError2("run cleanup currently requires --all.");
|
|
7658
7902
|
}
|
|
@@ -7671,20 +7915,25 @@ async function executeRun(context, args) {
|
|
|
7671
7915
|
}
|
|
7672
7916
|
case "show": {
|
|
7673
7917
|
let pending = rest;
|
|
7918
|
+
const rawResult = takeFlag(pending, "--raw");
|
|
7919
|
+
pending = rawResult.rest;
|
|
7674
7920
|
const run = takeOption(pending, "--run");
|
|
7675
7921
|
pending = run.rest;
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
7922
|
+
const positionalRunId = pending.length > 0 && pending[0] && !pending[0].startsWith("-") ? pending[0] : undefined;
|
|
7923
|
+
const extra = positionalRunId ? pending.slice(1) : pending;
|
|
7924
|
+
requireNoExtraArgs(extra, "rig run show <id>|--run <id> [--raw]");
|
|
7925
|
+
const runId = run.value ?? positionalRunId;
|
|
7926
|
+
if (!runId) {
|
|
7927
|
+
throw new CliError2("run show requires a run id.");
|
|
7679
7928
|
}
|
|
7680
|
-
const record = readAuthorityRun4(context.projectRoot,
|
|
7929
|
+
const record = readAuthorityRun4(context.projectRoot, runId) ?? normalizeRemoteRunDetails2(await getRunDetailsViaServer(context, runId).catch(() => ({})));
|
|
7681
7930
|
if (!record) {
|
|
7682
|
-
throw new CliError2(`Run not found: ${
|
|
7931
|
+
throw new CliError2(`Run not found: ${runId}`, 2);
|
|
7683
7932
|
}
|
|
7684
7933
|
if (context.outputMode === "text") {
|
|
7685
|
-
|
|
7934
|
+
printFormattedOutput(rawResult.value ? JSON.stringify(record, null, 2) : formatRunCard(record));
|
|
7686
7935
|
}
|
|
7687
|
-
return { ok: true, group: "run", command, details: record };
|
|
7936
|
+
return { ok: true, group: "run", command, details: { ...record, rawOutput: rawResult.value } };
|
|
7688
7937
|
}
|
|
7689
7938
|
case "timeline": {
|
|
7690
7939
|
let pending = rest;
|
|
@@ -7692,7 +7941,7 @@ async function executeRun(context, args) {
|
|
|
7692
7941
|
pending = run.rest;
|
|
7693
7942
|
const follow = takeFlag(pending, "--follow");
|
|
7694
7943
|
pending = follow.rest;
|
|
7695
|
-
requireNoExtraArgs(pending, "
|
|
7944
|
+
requireNoExtraArgs(pending, "rig run timeline --run <id> [--follow]");
|
|
7696
7945
|
if (!run.value) {
|
|
7697
7946
|
throw new CliError2("run timeline requires --run <id>.");
|
|
7698
7947
|
}
|
|
@@ -7729,7 +7978,7 @@ async function executeRun(context, args) {
|
|
|
7729
7978
|
pending = pollMs.rest;
|
|
7730
7979
|
const positionalRunId = pending.length > 0 ? pending[0] : undefined;
|
|
7731
7980
|
const extra = positionalRunId ? pending.slice(1) : pending;
|
|
7732
|
-
requireNoExtraArgs(extra, "
|
|
7981
|
+
requireNoExtraArgs(extra, "rig run attach <run-id>|--run <run-id> [--message <text>] [--once|--follow] [--poll-ms <ms>]");
|
|
7733
7982
|
const runId = runOption.value ?? positionalRunId;
|
|
7734
7983
|
if (!runId) {
|
|
7735
7984
|
throw new CliError2("run attach requires a run id.", 2);
|
|
@@ -7749,28 +7998,18 @@ async function executeRun(context, args) {
|
|
|
7749
7998
|
return { ok: true, group: "run", command, details: { ...attached, steered: attached.steered || steered } };
|
|
7750
7999
|
}
|
|
7751
8000
|
case "status": {
|
|
7752
|
-
requireNoExtraArgs(rest, "
|
|
8001
|
+
requireNoExtraArgs(rest, "rig run status");
|
|
7753
8002
|
if (context.dryRun) {
|
|
7754
8003
|
if (context.outputMode === "text") {
|
|
7755
8004
|
console.log("[dry-run] rig run status");
|
|
7756
8005
|
}
|
|
7757
8006
|
return { ok: true, group: "run", command };
|
|
7758
8007
|
}
|
|
7759
|
-
const summary =
|
|
8008
|
+
const summary = isRemoteConnectionSelected2(context.projectRoot) ? buildServerRunStatus(await listRunsViaServer(context, { limit: 100 })) : runStatus(context.projectRoot, runtimeContext);
|
|
7760
8009
|
const activeRuns = Array.isArray(summary.activeRuns) ? summary.activeRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7761
8010
|
const recentRuns = Array.isArray(summary.recentRuns) ? summary.recentRuns.filter((run) => Boolean(run && typeof run === "object" && !Array.isArray(run))) : [];
|
|
7762
8011
|
if (context.outputMode === "text") {
|
|
7763
|
-
|
|
7764
|
-
for (const run of activeRuns) {
|
|
7765
|
-
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
7766
|
-
}
|
|
7767
|
-
if (recentRuns.length > 0) {
|
|
7768
|
-
console.log("");
|
|
7769
|
-
console.log("Recent runs:");
|
|
7770
|
-
for (const run of recentRuns) {
|
|
7771
|
-
console.log(`- ${runStringField(run, "runId", "(unknown-run)")} \xB7 ${runStringField(run, "status", "unknown")} \xB7 ${runStringField(run, "taskId", runDisplayTitle(run))}`);
|
|
7772
|
-
}
|
|
7773
|
-
}
|
|
8012
|
+
printFormattedOutput(formatRunStatus({ activeRuns, recentRuns, runs: Array.isArray(summary.runs) ? summary.runs : [...activeRuns, ...recentRuns] }, { source: isRemoteConnectionSelected2(context.projectRoot) ? "server" : "local" }));
|
|
7774
8013
|
}
|
|
7775
8014
|
return { ok: true, group: "run", command, details: summary };
|
|
7776
8015
|
}
|
|
@@ -7794,7 +8033,7 @@ async function executeRun(context, args) {
|
|
|
7794
8033
|
pending = pollResult.rest;
|
|
7795
8034
|
const noServerResult = takeFlag(pending, "--no-server");
|
|
7796
8035
|
pending = noServerResult.rest;
|
|
7797
|
-
requireNoExtraArgs(pending, "
|
|
8036
|
+
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]");
|
|
7798
8037
|
if (promptEpicResult.value && noEpicPromptResult.value) {
|
|
7799
8038
|
throw new CliError2("Cannot use --prompt-epic and --no-epic-prompt together.");
|
|
7800
8039
|
}
|
|
@@ -7842,7 +8081,7 @@ async function executeRun(context, args) {
|
|
|
7842
8081
|
};
|
|
7843
8082
|
}
|
|
7844
8083
|
case "resume": {
|
|
7845
|
-
requireNoExtraArgs(rest, "
|
|
8084
|
+
requireNoExtraArgs(rest, "rig run resume");
|
|
7846
8085
|
if (context.dryRun) {
|
|
7847
8086
|
if (context.outputMode === "text") {
|
|
7848
8087
|
console.log("[dry-run] rig run resume");
|
|
@@ -7856,7 +8095,7 @@ async function executeRun(context, args) {
|
|
|
7856
8095
|
return { ok: true, group: "run", command, details: resumed };
|
|
7857
8096
|
}
|
|
7858
8097
|
case "restart": {
|
|
7859
|
-
requireNoExtraArgs(rest, "
|
|
8098
|
+
requireNoExtraArgs(rest, "rig run restart");
|
|
7860
8099
|
if (context.dryRun) {
|
|
7861
8100
|
if (context.outputMode === "text") {
|
|
7862
8101
|
console.log("[dry-run] rig run restart");
|
|
@@ -7873,7 +8112,7 @@ async function executeRun(context, args) {
|
|
|
7873
8112
|
const runOption = takeOption(rest, "--run");
|
|
7874
8113
|
const positionalRunId = runOption.rest.length > 0 ? runOption.rest[0] : undefined;
|
|
7875
8114
|
const extra = positionalRunId ? runOption.rest.slice(1) : runOption.rest;
|
|
7876
|
-
requireNoExtraArgs(extra, "
|
|
8115
|
+
requireNoExtraArgs(extra, "rig run stop [<run-id>|--run <id>]");
|
|
7877
8116
|
const runId = runOption.value ?? positionalRunId;
|
|
7878
8117
|
if (context.dryRun) {
|
|
7879
8118
|
return {
|
|
@@ -8011,73 +8250,425 @@ async function executeServer(context, args, options) {
|
|
|
8011
8250
|
throw new CliError2(`Unknown server command: ${command}`);
|
|
8012
8251
|
}
|
|
8013
8252
|
}
|
|
8014
|
-
|
|
8015
|
-
// packages/cli/src/commands/task.ts
|
|
8016
|
-
import { readFileSync as readFileSync9 } from "fs";
|
|
8017
|
-
import { spawnSync as spawnSync3 } from "child_process";
|
|
8018
|
-
import { resolve as resolve20 } from "path";
|
|
8019
|
-
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
8020
|
-
import {
|
|
8021
|
-
taskArtifactDir,
|
|
8022
|
-
taskArtifacts,
|
|
8023
|
-
taskArtifactWrite,
|
|
8024
|
-
taskDeps,
|
|
8025
|
-
taskInfo,
|
|
8026
|
-
taskLookup as taskLookup2,
|
|
8027
|
-
taskReady,
|
|
8028
|
-
taskRecord,
|
|
8029
|
-
taskReopen,
|
|
8030
|
-
taskScope,
|
|
8031
|
-
taskStatus as taskStatus2,
|
|
8032
|
-
taskValidate,
|
|
8033
|
-
taskVerify
|
|
8034
|
-
} from "@rig/runtime/control-plane/native/task-ops";
|
|
8035
|
-
|
|
8036
|
-
// packages/cli/src/commands/_task-picker.ts
|
|
8037
|
-
import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
|
|
8038
|
-
function taskId2(task) {
|
|
8039
|
-
return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
|
|
8253
|
+
|
|
8254
|
+
// packages/cli/src/commands/task.ts
|
|
8255
|
+
import { readFileSync as readFileSync9 } from "fs";
|
|
8256
|
+
import { spawnSync as spawnSync3 } from "child_process";
|
|
8257
|
+
import { resolve as resolve20 } from "path";
|
|
8258
|
+
import { cancel as cancel4, confirm as confirm2, isCancel as isCancel4 } from "@clack/prompts";
|
|
8259
|
+
import {
|
|
8260
|
+
taskArtifactDir,
|
|
8261
|
+
taskArtifacts,
|
|
8262
|
+
taskArtifactWrite,
|
|
8263
|
+
taskDeps,
|
|
8264
|
+
taskInfo,
|
|
8265
|
+
taskLookup as taskLookup2,
|
|
8266
|
+
taskReady,
|
|
8267
|
+
taskRecord,
|
|
8268
|
+
taskReopen,
|
|
8269
|
+
taskScope,
|
|
8270
|
+
taskStatus as taskStatus2,
|
|
8271
|
+
taskValidate,
|
|
8272
|
+
taskVerify
|
|
8273
|
+
} from "@rig/runtime/control-plane/native/task-ops";
|
|
8274
|
+
|
|
8275
|
+
// packages/cli/src/commands/_task-picker.ts
|
|
8276
|
+
import { cancel as cancel3, isCancel as isCancel3, select as select3 } from "@clack/prompts";
|
|
8277
|
+
function taskId2(task) {
|
|
8278
|
+
return typeof task.id === "string" && task.id.trim() ? task.id : "<unknown>";
|
|
8279
|
+
}
|
|
8280
|
+
async function selectTaskWithTextPicker(tasks, io = {}) {
|
|
8281
|
+
if (tasks.length === 0)
|
|
8282
|
+
return null;
|
|
8283
|
+
if (tasks.length === 1)
|
|
8284
|
+
return tasks[0];
|
|
8285
|
+
const isTty = io.isTty ?? Boolean(process.stdin.isTTY && process.stdout.isTTY);
|
|
8286
|
+
if (!isTty) {
|
|
8287
|
+
throw new Error("task run requires an interactive terminal to pick a task; pass --task <id>, --next, or --detach with a task id.");
|
|
8288
|
+
}
|
|
8289
|
+
if (io.prompt || io.renderer) {
|
|
8290
|
+
const prompt = io.prompt ?? promptForTaskSelection;
|
|
8291
|
+
const renderer = io.renderer ?? { writeLine: (line) => process.stdout.write(`${line}
|
|
8292
|
+
`) };
|
|
8293
|
+
renderer.writeLine("Select Rig task:");
|
|
8294
|
+
for (const row of renderTaskPickerRows(tasks))
|
|
8295
|
+
renderer.writeLine(` ${row}`);
|
|
8296
|
+
const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
|
|
8297
|
+
if (!answer2)
|
|
8298
|
+
return null;
|
|
8299
|
+
if (/^\d+$/.test(answer2)) {
|
|
8300
|
+
const index2 = Number.parseInt(answer2, 10) - 1;
|
|
8301
|
+
return tasks[index2] ?? null;
|
|
8302
|
+
}
|
|
8303
|
+
return tasks.find((task) => taskId2(task) === answer2) ?? null;
|
|
8304
|
+
}
|
|
8305
|
+
const options = tasks.map((task, index2) => ({
|
|
8306
|
+
value: `${index2}`,
|
|
8307
|
+
label: `${taskId2(task)} \xB7 ${typeof task.title === "string" && task.title.trim() ? task.title.trim() : "Untitled task"}`,
|
|
8308
|
+
hint: typeof task.status === "string" && task.status.trim() ? task.status.trim() : undefined
|
|
8309
|
+
}));
|
|
8310
|
+
const answer = await select3({
|
|
8311
|
+
message: "Select Rig task",
|
|
8312
|
+
options
|
|
8313
|
+
});
|
|
8314
|
+
if (isCancel3(answer)) {
|
|
8315
|
+
cancel3("No task selected.");
|
|
8316
|
+
return null;
|
|
8317
|
+
}
|
|
8318
|
+
const index = Number.parseInt(String(answer), 10);
|
|
8319
|
+
return Number.isFinite(index) ? tasks[index] ?? null : null;
|
|
8320
|
+
}
|
|
8321
|
+
|
|
8322
|
+
// packages/cli/src/commands/_help-catalog.ts
|
|
8323
|
+
import { intro as intro3, log as log4, note as note4, outro as outro3 } from "@clack/prompts";
|
|
8324
|
+
import pc4 from "picocolors";
|
|
8325
|
+
var TOP_LEVEL_SECTIONS = [
|
|
8326
|
+
{
|
|
8327
|
+
title: "Server",
|
|
8328
|
+
subtitle: "choose the local or remote Rig server that owns this repo",
|
|
8329
|
+
commands: [
|
|
8330
|
+
{ command: "rig server status", description: "Show the selected local/remote server for this repo." },
|
|
8331
|
+
{ command: "rig server use local", description: "Switch this repo back to the local Rig server." },
|
|
8332
|
+
{ command: "rig server add <alias> <url>", description: "Save a remote Rig server alias." },
|
|
8333
|
+
{ command: "rig server use <alias>", description: "Switch this repo to a saved remote server." },
|
|
8334
|
+
{ command: "rig server list", description: "Show saved server aliases, including local." }
|
|
8335
|
+
]
|
|
8336
|
+
},
|
|
8337
|
+
{
|
|
8338
|
+
title: "Tasks",
|
|
8339
|
+
subtitle: "find work, inspect it, and submit Pi-backed workers",
|
|
8340
|
+
commands: [
|
|
8341
|
+
{ command: "rig task list", description: "List tasks from the selected task source/server." },
|
|
8342
|
+
{ command: "rig task next", description: "Show the next matching task as a selected-task card." },
|
|
8343
|
+
{ command: "rig task show <id>", description: "Show a human task summary; add --raw or --json for the full payload." },
|
|
8344
|
+
{ command: "rig task run <id|--next> [--detach]", description: "Submit a task run; interactive mode follows with bundled Pi." }
|
|
8345
|
+
]
|
|
8346
|
+
},
|
|
8347
|
+
{
|
|
8348
|
+
title: "Runs",
|
|
8349
|
+
subtitle: "observe, attach to, and stop live or recent runs",
|
|
8350
|
+
commands: [
|
|
8351
|
+
{ command: "rig run list", description: "List recent runs from the selected server or local state." },
|
|
8352
|
+
{ command: "rig run show <id>", description: "Show a human run summary; add --raw or --json for the full payload." },
|
|
8353
|
+
{ command: "rig run attach <id> --follow", description: "Open the native bundled Pi live view for a worker run." },
|
|
8354
|
+
{ command: "rig run stop <id>", description: "Request cancellation for a running worker." }
|
|
8355
|
+
]
|
|
8356
|
+
},
|
|
8357
|
+
{
|
|
8358
|
+
title: "Review / inbox",
|
|
8359
|
+
subtitle: "clear blocked runs and configure completion review",
|
|
8360
|
+
commands: [
|
|
8361
|
+
{ command: "rig inbox approvals", description: "List pending approval requests from local/server run state." },
|
|
8362
|
+
{ command: "rig inbox inputs", description: "List pending user-input requests from local/server run state." },
|
|
8363
|
+
{ command: "rig review show|set", description: "Inspect or change the review gate policy." }
|
|
8364
|
+
]
|
|
8365
|
+
},
|
|
8366
|
+
{
|
|
8367
|
+
title: "Health / setup",
|
|
8368
|
+
subtitle: "bootstrap and diagnose the repo/server/GitHub/Pi path",
|
|
8369
|
+
commands: [
|
|
8370
|
+
{ command: "rig init", description: "Interactive setup: config, GitHub auth, task source, server, checkout, Pi." },
|
|
8371
|
+
{ command: "rig doctor", description: "Diagnose project/server/GitHub/task/Pi wiring." },
|
|
8372
|
+
{ command: "rig github auth status", description: "Show GitHub auth state on the selected Rig server." }
|
|
8373
|
+
]
|
|
8374
|
+
}
|
|
8375
|
+
];
|
|
8376
|
+
var PRIMARY_GROUPS = [
|
|
8377
|
+
{
|
|
8378
|
+
name: "server",
|
|
8379
|
+
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
8380
|
+
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
8381
|
+
commands: [
|
|
8382
|
+
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
8383
|
+
{ command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
|
|
8384
|
+
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
8385
|
+
{ command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
|
|
8386
|
+
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
8387
|
+
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
|
|
8388
|
+
],
|
|
8389
|
+
examples: [
|
|
8390
|
+
"rig server status",
|
|
8391
|
+
"rig server add prod https://where.rig-does.work",
|
|
8392
|
+
"rig server use prod",
|
|
8393
|
+
"rig server use local",
|
|
8394
|
+
"rig server start --port 3773"
|
|
8395
|
+
],
|
|
8396
|
+
next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
|
|
8397
|
+
advanced: ["Compatibility alias: `rig connect ...` remains callable."]
|
|
8398
|
+
},
|
|
8399
|
+
{
|
|
8400
|
+
name: "task",
|
|
8401
|
+
summary: "Find work, start Pi-backed runs, and validate task results.",
|
|
8402
|
+
usage: ["rig task <list|next|show|run> [options]"],
|
|
8403
|
+
commands: [
|
|
8404
|
+
{ command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
|
|
8405
|
+
{ command: "next [filters]", description: "Render the next matching task as a selected-task card.", primary: true },
|
|
8406
|
+
{ command: "show <id>|--task <id> [--raw]", description: "Show a human task summary; --raw prints the full payload.", primary: true },
|
|
8407
|
+
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
8408
|
+
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
8409
|
+
{ command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
|
|
8410
|
+
{ command: "report-bug", description: "Create a structured bug report/task." }
|
|
8411
|
+
],
|
|
8412
|
+
examples: [
|
|
8413
|
+
"rig task list --assignee @me --limit 20",
|
|
8414
|
+
"rig task next",
|
|
8415
|
+
"rig task show 123 --raw",
|
|
8416
|
+
"rig task run --next",
|
|
8417
|
+
"rig task run #123 --runtime-adapter pi",
|
|
8418
|
+
"rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
|
|
8419
|
+
],
|
|
8420
|
+
next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
|
|
8421
|
+
},
|
|
8422
|
+
{
|
|
8423
|
+
name: "run",
|
|
8424
|
+
summary: "Observe, attach to, and control Rig runs.",
|
|
8425
|
+
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
8426
|
+
commands: [
|
|
8427
|
+
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
8428
|
+
{ command: "status", description: "Render active and recent run groups.", primary: true },
|
|
8429
|
+
{ command: "show <id>|--run <id> [--raw]", description: "Show a human run summary; --raw prints the full payload.", primary: true },
|
|
8430
|
+
{ command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; --follow launches native bundled Pi for live Pi runs.", primary: true },
|
|
8431
|
+
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
8432
|
+
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
8433
|
+
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
8434
|
+
],
|
|
8435
|
+
examples: [
|
|
8436
|
+
"rig run list",
|
|
8437
|
+
"rig run status",
|
|
8438
|
+
"rig run show <run-id>",
|
|
8439
|
+
"rig run attach <run-id> --follow",
|
|
8440
|
+
"rig run stop <run-id>"
|
|
8441
|
+
],
|
|
8442
|
+
next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
|
|
8443
|
+
},
|
|
8444
|
+
{
|
|
8445
|
+
name: "inbox",
|
|
8446
|
+
summary: "Review approval and user-input requests that block worker runs.",
|
|
8447
|
+
usage: ["rig inbox <approvals|approve|inputs|respond> [options]"],
|
|
8448
|
+
commands: [
|
|
8449
|
+
{ command: "approvals [--run <id>] [--task <id>]", description: "List pending approvals.", primary: true },
|
|
8450
|
+
{ command: "inputs [--run <id>] [--task <id>]", description: "List pending user-input requests.", primary: true },
|
|
8451
|
+
{ command: "approve --run <id> --request <id> --decision approve|reject", description: "Resolve an approval request." },
|
|
8452
|
+
{ command: "respond --run <id> --request <id> --answer key=value", description: "Answer a user-input request." }
|
|
8453
|
+
],
|
|
8454
|
+
examples: [
|
|
8455
|
+
"rig inbox approvals",
|
|
8456
|
+
"rig inbox inputs --run <run-id>",
|
|
8457
|
+
"rig inbox approve --run <run-id> --request <request-id> --decision approve"
|
|
8458
|
+
],
|
|
8459
|
+
next: ["Rejoin the run after resolving a block: `rig run attach <run-id> --follow`."]
|
|
8460
|
+
},
|
|
8461
|
+
{
|
|
8462
|
+
name: "review",
|
|
8463
|
+
summary: "Inspect or change completion review gate policy.",
|
|
8464
|
+
usage: ["rig review <show|set>"],
|
|
8465
|
+
commands: [
|
|
8466
|
+
{ command: "show", description: "Show current review gate settings.", primary: true },
|
|
8467
|
+
{ command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider.", primary: true }
|
|
8468
|
+
],
|
|
8469
|
+
examples: ["rig review show", "rig review set required --provider greptile"],
|
|
8470
|
+
next: ["Use `rig inbox approvals` for blocked run handoffs."]
|
|
8471
|
+
},
|
|
8472
|
+
{
|
|
8473
|
+
name: "init",
|
|
8474
|
+
summary: "Set up Rig for this repo: server, GitHub auth, checkout strategy, task source, and Pi wiring.",
|
|
8475
|
+
usage: ["rig init [--yes] [--server local|remote] [--repo owner/repo] [--remote-url <url>]"],
|
|
8476
|
+
commands: [
|
|
8477
|
+
{ command: "init", description: "Interactive setup wizard for a new or existing Rig repo.", primary: true },
|
|
8478
|
+
{ command: "init --yes", description: "Non-interactive setup using detected/default settings.", primary: true },
|
|
8479
|
+
{ command: "init --server remote --remote-url <url>", description: "Link this repo to a remote Rig server.", primary: true },
|
|
8480
|
+
{ command: "init --repair", description: "Repair missing private state without replacing project config." }
|
|
8481
|
+
],
|
|
8482
|
+
examples: [
|
|
8483
|
+
"rig init",
|
|
8484
|
+
"rig init --yes --repo humanity-org/humanwork",
|
|
8485
|
+
"rig init --server remote --remote-url https://where.rig-does.work --repo owner/repo"
|
|
8486
|
+
],
|
|
8487
|
+
next: ["After init, run `rig server status`.", "Then use `rig task list` and `rig task run --next` for day-to-day work."]
|
|
8488
|
+
},
|
|
8489
|
+
{
|
|
8490
|
+
name: "doctor",
|
|
8491
|
+
summary: "Diagnostics for project/server/GitHub/Pi state.",
|
|
8492
|
+
usage: ["rig doctor"],
|
|
8493
|
+
commands: [
|
|
8494
|
+
{ command: "doctor", description: "Run setup and runtime diagnostics.", primary: true },
|
|
8495
|
+
{ command: "check", description: "Compatibility spelling for diagnostics." }
|
|
8496
|
+
],
|
|
8497
|
+
examples: ["rig doctor", "rig doctor --json"],
|
|
8498
|
+
next: ["Use `rig server status` and `rig github auth status` to inspect common failure points."]
|
|
8499
|
+
},
|
|
8500
|
+
{
|
|
8501
|
+
name: "github",
|
|
8502
|
+
summary: "GitHub auth helpers for the selected Rig server.",
|
|
8503
|
+
usage: ["rig github auth <status|import-gh|token>"],
|
|
8504
|
+
commands: [
|
|
8505
|
+
{ command: "auth status", description: "Show GitHub auth state.", primary: true },
|
|
8506
|
+
{ command: "auth import-gh", description: "Import the current `gh` token into the selected server." },
|
|
8507
|
+
{ command: "auth token --token <token>", description: "Store a token on the selected server." }
|
|
8508
|
+
],
|
|
8509
|
+
examples: ["rig github auth status", "rig github auth import-gh"],
|
|
8510
|
+
next: ["After auth is valid, use `rig task run --next`."]
|
|
8511
|
+
}
|
|
8512
|
+
];
|
|
8513
|
+
var ADVANCED_GROUPS = [
|
|
8514
|
+
{ 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." }] },
|
|
8515
|
+
{ name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
|
|
8516
|
+
{ 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." }] },
|
|
8517
|
+
{ name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
|
|
8518
|
+
{ name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
|
|
8519
|
+
{ name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
|
|
8520
|
+
{ name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
|
|
8521
|
+
{ name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
|
|
8522
|
+
{ name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
|
|
8523
|
+
{ name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
|
|
8524
|
+
{ name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
|
|
8525
|
+
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
8526
|
+
{ name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
|
|
8527
|
+
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
8528
|
+
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
8529
|
+
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
8530
|
+
];
|
|
8531
|
+
var ADVANCED_COMMANDS = [
|
|
8532
|
+
{ command: "rig server task-run ...", description: "Internal server-owned task execution entry point." },
|
|
8533
|
+
{ command: "rig server notify-test [--event <type>]", description: "Internal event notification smoke command." },
|
|
8534
|
+
{ command: "rig run start|start-serial|start-parallel", description: "Compatibility local run starters; prefer `rig task run ...`." },
|
|
8535
|
+
{ command: "rig setup install-agent-shell", description: "Development helper for materializing the agent shell." },
|
|
8536
|
+
{ command: "rig remote orchestrate-*", description: "Compatibility remote orchestration commands." }
|
|
8537
|
+
];
|
|
8538
|
+
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
8539
|
+
function heading(title) {
|
|
8540
|
+
return pc4.bold(pc4.cyan(title));
|
|
8541
|
+
}
|
|
8542
|
+
function commandLine(command, description) {
|
|
8543
|
+
const commandColumn = command.length >= 38 ? `${command} ` : command.padEnd(38);
|
|
8544
|
+
return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
|
|
8545
|
+
}
|
|
8546
|
+
function renderCommandBlock(commands) {
|
|
8547
|
+
return commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8548
|
+
`);
|
|
8549
|
+
}
|
|
8550
|
+
function renderGroup(group) {
|
|
8551
|
+
const lines = [
|
|
8552
|
+
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
8553
|
+
"",
|
|
8554
|
+
pc4.bold("Usage"),
|
|
8555
|
+
...group.usage.map((line) => ` ${line}`),
|
|
8556
|
+
"",
|
|
8557
|
+
pc4.bold("Commands"),
|
|
8558
|
+
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
8559
|
+
];
|
|
8560
|
+
if (group.examples?.length) {
|
|
8561
|
+
lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
|
|
8562
|
+
}
|
|
8563
|
+
if (group.next?.length) {
|
|
8564
|
+
lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
8565
|
+
}
|
|
8566
|
+
if (group.advanced?.length) {
|
|
8567
|
+
lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
8568
|
+
}
|
|
8569
|
+
return lines.join(`
|
|
8570
|
+
`);
|
|
8571
|
+
}
|
|
8572
|
+
function renderTopLevelHelp() {
|
|
8573
|
+
return [
|
|
8574
|
+
`${heading("rig")} ${pc4.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
8575
|
+
pc4.dim("Current path: select a server, choose a task, submit a run, attach with native Pi, clear inbox/review gates."),
|
|
8576
|
+
"",
|
|
8577
|
+
...TOP_LEVEL_SECTIONS.flatMap((section) => [
|
|
8578
|
+
`${pc4.bold(pc4.magenta(`\u25C7 ${section.title}`))} \u2014 ${pc4.dim(section.subtitle)}`,
|
|
8579
|
+
renderCommandBlock(section.commands),
|
|
8580
|
+
""
|
|
8581
|
+
]),
|
|
8582
|
+
pc4.dim("More: `rig help --advanced` for dev/compatibility commands; `rig <group> --help` for rich per-group help; `rig --version` for the installed version."),
|
|
8583
|
+
"",
|
|
8584
|
+
pc4.bold("Global options"),
|
|
8585
|
+
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8586
|
+
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8587
|
+
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
8588
|
+
].join(`
|
|
8589
|
+
`).trimEnd();
|
|
8590
|
+
}
|
|
8591
|
+
function renderAdvancedHelp() {
|
|
8592
|
+
return [
|
|
8593
|
+
`${heading("rig advanced")} \u2014 compatibility, diagnostics, and internal surfaces`,
|
|
8594
|
+
"",
|
|
8595
|
+
pc4.bold("Primary groups"),
|
|
8596
|
+
" server, task, run, inbox, review, init, doctor, github",
|
|
8597
|
+
"",
|
|
8598
|
+
pc4.bold("Advanced commands"),
|
|
8599
|
+
...ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)),
|
|
8600
|
+
"",
|
|
8601
|
+
pc4.bold("Advanced groups"),
|
|
8602
|
+
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
8603
|
+
"",
|
|
8604
|
+
pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, `rig run`, `rig inbox`, and `rig review` for day-to-day work.")
|
|
8605
|
+
].join(`
|
|
8606
|
+
`);
|
|
8607
|
+
}
|
|
8608
|
+
function renderGroupHelp(groupName) {
|
|
8609
|
+
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
8610
|
+
return group ? renderGroup(group) : null;
|
|
8040
8611
|
}
|
|
8041
|
-
|
|
8042
|
-
|
|
8043
|
-
|
|
8044
|
-
|
|
8045
|
-
|
|
8046
|
-
|
|
8047
|
-
|
|
8048
|
-
throw new Error("task run requires an interactive terminal to pick a task; pass --task <id>, --next, or --detach with a task id.");
|
|
8612
|
+
function shouldUseClackOutput2() {
|
|
8613
|
+
return Boolean(process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
|
|
8614
|
+
}
|
|
8615
|
+
function printTopLevelHelp() {
|
|
8616
|
+
if (!shouldUseClackOutput2()) {
|
|
8617
|
+
console.log(renderTopLevelHelp());
|
|
8618
|
+
return;
|
|
8049
8619
|
}
|
|
8050
|
-
|
|
8051
|
-
|
|
8052
|
-
|
|
8053
|
-
`) };
|
|
8054
|
-
renderer.writeLine("Select Rig task:");
|
|
8055
|
-
for (const row of renderTaskPickerRows(tasks))
|
|
8056
|
-
renderer.writeLine(` ${row}`);
|
|
8057
|
-
const answer2 = (await prompt(`Task [1-${tasks.length}] or id: `)).trim();
|
|
8058
|
-
if (!answer2)
|
|
8059
|
-
return null;
|
|
8060
|
-
if (/^\d+$/.test(answer2)) {
|
|
8061
|
-
const index2 = Number.parseInt(answer2, 10) - 1;
|
|
8062
|
-
return tasks[index2] ?? null;
|
|
8063
|
-
}
|
|
8064
|
-
return tasks.find((task) => taskId2(task) === answer2) ?? null;
|
|
8620
|
+
intro3("rig");
|
|
8621
|
+
for (const section of TOP_LEVEL_SECTIONS) {
|
|
8622
|
+
note4(renderCommandBlock(section.commands), `${section.title} \u2014 ${section.subtitle}`);
|
|
8065
8623
|
}
|
|
8066
|
-
|
|
8067
|
-
|
|
8068
|
-
|
|
8069
|
-
|
|
8070
|
-
|
|
8071
|
-
|
|
8072
|
-
|
|
8073
|
-
|
|
8074
|
-
|
|
8075
|
-
|
|
8076
|
-
|
|
8077
|
-
|
|
8624
|
+
log4.info("More: rig help --advanced \xB7 rig <group> --help \xB7 rig --version");
|
|
8625
|
+
note4([
|
|
8626
|
+
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
8627
|
+
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
8628
|
+
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
8629
|
+
].join(`
|
|
8630
|
+
`), "Global options");
|
|
8631
|
+
outro3("Server \u2192 task \u2192 run \u2192 inbox/review.");
|
|
8632
|
+
}
|
|
8633
|
+
function printAdvancedHelp() {
|
|
8634
|
+
if (!shouldUseClackOutput2()) {
|
|
8635
|
+
console.log(renderAdvancedHelp());
|
|
8636
|
+
return;
|
|
8078
8637
|
}
|
|
8079
|
-
|
|
8080
|
-
|
|
8638
|
+
intro3("rig advanced");
|
|
8639
|
+
note4(ADVANCED_COMMANDS.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8640
|
+
`), "Advanced commands");
|
|
8641
|
+
note4(ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)).join(`
|
|
8642
|
+
`), "Advanced groups");
|
|
8643
|
+
outro3("Primary daily flow: rig server \xB7 rig task \xB7 rig run \xB7 rig inbox \xB7 rig review.");
|
|
8644
|
+
}
|
|
8645
|
+
function printGroupHelpDocument(groupName) {
|
|
8646
|
+
const rendered = renderGroupHelp(groupName) ?? renderTopLevelHelp();
|
|
8647
|
+
if (!shouldUseClackOutput2()) {
|
|
8648
|
+
console.log(rendered);
|
|
8649
|
+
return;
|
|
8650
|
+
}
|
|
8651
|
+
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
8652
|
+
if (!group) {
|
|
8653
|
+
printTopLevelHelp();
|
|
8654
|
+
return;
|
|
8655
|
+
}
|
|
8656
|
+
intro3(`rig ${group.name}`);
|
|
8657
|
+
note4(group.summary, "Purpose");
|
|
8658
|
+
note4(group.usage.join(`
|
|
8659
|
+
`), "Usage");
|
|
8660
|
+
note4(group.commands.map((entry) => commandLine(entry.command, entry.description)).join(`
|
|
8661
|
+
`), "Commands");
|
|
8662
|
+
if (group.examples?.length)
|
|
8663
|
+
note4(group.examples.map((line) => `$ ${line}`).join(`
|
|
8664
|
+
`), "Examples");
|
|
8665
|
+
if (group.next?.length)
|
|
8666
|
+
note4(group.next.map((line) => `\u203A ${line}`).join(`
|
|
8667
|
+
`), "Next steps");
|
|
8668
|
+
if (group.advanced?.length)
|
|
8669
|
+
log4.info(group.advanced.join(`
|
|
8670
|
+
`));
|
|
8671
|
+
outro3("Run with --json when scripts need structured output.");
|
|
8081
8672
|
}
|
|
8082
8673
|
|
|
8083
8674
|
// packages/cli/src/commands/task.ts
|
|
@@ -8231,27 +8822,30 @@ function summarizeTask(task, options = {}) {
|
|
|
8231
8822
|
...options.raw ? { raw: raw ?? task } : {}
|
|
8232
8823
|
};
|
|
8233
8824
|
}
|
|
8234
|
-
function printTaskSummary(task) {
|
|
8235
|
-
console.log(formatTaskList([task]));
|
|
8236
|
-
}
|
|
8237
8825
|
async function validatorRegistryForTaskCommands(projectRoot) {
|
|
8238
8826
|
return buildPluginHostContext(projectRoot).then((ctx) => ctx?.validatorRegistry ?? undefined).catch(() => {
|
|
8239
8827
|
return;
|
|
8240
8828
|
});
|
|
8241
8829
|
}
|
|
8242
8830
|
async function executeTask(context, args, options) {
|
|
8243
|
-
|
|
8831
|
+
if (args.length === 0) {
|
|
8832
|
+
if (context.outputMode === "text") {
|
|
8833
|
+
printGroupHelpDocument("task");
|
|
8834
|
+
}
|
|
8835
|
+
return { ok: true, group: "task", command: "help" };
|
|
8836
|
+
}
|
|
8837
|
+
const [command = "help", ...rest] = args;
|
|
8244
8838
|
switch (command) {
|
|
8245
8839
|
case "list": {
|
|
8246
8840
|
let pending = rest;
|
|
8247
8841
|
const rawResult = takeFlag(pending, "--raw");
|
|
8248
8842
|
pending = rawResult.rest;
|
|
8249
8843
|
const { filters, rest: remaining } = parseTaskFilters(pending);
|
|
8250
|
-
requireNoExtraArgs(remaining, "
|
|
8844
|
+
requireNoExtraArgs(remaining, "rig task list [--raw] [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
8251
8845
|
const tasks = await listWorkspaceTasksViaServer(context, filters);
|
|
8252
8846
|
if (context.outputMode === "text") {
|
|
8253
8847
|
const renderedTasks = rawResult.value ? tasks.map((task) => summarizeTask(task, { raw: true })) : tasks.map((task) => summarizeTask(task));
|
|
8254
|
-
|
|
8848
|
+
printFormattedOutput(formatTaskList(renderedTasks, { raw: rawResult.value }));
|
|
8255
8849
|
}
|
|
8256
8850
|
return {
|
|
8257
8851
|
ok: true,
|
|
@@ -8261,10 +8855,13 @@ async function executeTask(context, args, options) {
|
|
|
8261
8855
|
};
|
|
8262
8856
|
}
|
|
8263
8857
|
case "show": {
|
|
8264
|
-
|
|
8858
|
+
let pending = rest;
|
|
8859
|
+
const rawResult = takeFlag(pending, "--raw");
|
|
8860
|
+
pending = rawResult.rest;
|
|
8861
|
+
const taskOption = takeOption(pending, "--task");
|
|
8265
8862
|
const positional = taskOption.rest.length > 0 && taskOption.rest[0] && !taskOption.rest[0].startsWith("-") ? taskOption.rest[0] : undefined;
|
|
8266
8863
|
const remaining = positional ? taskOption.rest.slice(1) : taskOption.rest;
|
|
8267
|
-
requireNoExtraArgs(remaining, "
|
|
8864
|
+
requireNoExtraArgs(remaining, "rig task show <id>|--task <id> [--raw]");
|
|
8268
8865
|
const taskId3 = normalizeTaskRunTaskId(taskOption.value ?? positional);
|
|
8269
8866
|
if (!taskId3)
|
|
8270
8867
|
throw new CliError2("task show requires a task id.", 2);
|
|
@@ -8272,19 +8869,20 @@ async function executeTask(context, args, options) {
|
|
|
8272
8869
|
if (!task)
|
|
8273
8870
|
throw new CliError2(`Task not found: ${taskId3}`, 3);
|
|
8274
8871
|
const summary = summarizeTask(task, { raw: true });
|
|
8275
|
-
if (context.outputMode === "text")
|
|
8276
|
-
|
|
8277
|
-
|
|
8872
|
+
if (context.outputMode === "text") {
|
|
8873
|
+
printFormattedOutput(rawResult.value ? JSON.stringify(summary, null, 2) : formatTaskDetails(summary));
|
|
8874
|
+
}
|
|
8875
|
+
return { ok: true, group: "task", command, details: { task: summary, raw: rawResult.value } };
|
|
8278
8876
|
}
|
|
8279
8877
|
case "next": {
|
|
8280
8878
|
const { filters, rest: remaining } = parseTaskFilters(rest);
|
|
8281
|
-
requireNoExtraArgs(remaining, "
|
|
8879
|
+
requireNoExtraArgs(remaining, "rig task next [--assignee <login|@me>] [--assigned-to <login|me|@me>] [--state open|closed] [--status <status>] [--limit <n>]");
|
|
8282
8880
|
const selected = await selectNextWorkspaceTaskViaServer(context, filters);
|
|
8283
8881
|
if (context.outputMode === "text") {
|
|
8284
8882
|
if (selected.task) {
|
|
8285
|
-
|
|
8883
|
+
printFormattedOutput(formatTaskCard(summarizeTask(selected.task, { raw: true }), { title: "Selected task", selected: true }));
|
|
8286
8884
|
} else {
|
|
8287
|
-
|
|
8885
|
+
printFormattedOutput("No matching tasks.\n\nNext\n\u203A Try `rig task list` to inspect available work.\n\u203A Check server: `rig server status`");
|
|
8288
8886
|
}
|
|
8289
8887
|
}
|
|
8290
8888
|
return {
|
|
@@ -8300,31 +8898,31 @@ async function executeTask(context, args, options) {
|
|
|
8300
8898
|
}
|
|
8301
8899
|
case "info": {
|
|
8302
8900
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8303
|
-
requireNoExtraArgs(remaining, "
|
|
8901
|
+
requireNoExtraArgs(remaining, "rig task info [--task <task-id>]");
|
|
8304
8902
|
await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, task || undefined));
|
|
8305
8903
|
return { ok: true, group: "task", command, details: { task: task || null } };
|
|
8306
8904
|
}
|
|
8307
8905
|
case "scope": {
|
|
8308
8906
|
const filesFlag = takeFlag(rest, "--files");
|
|
8309
8907
|
const { value: task, rest: remaining } = takeOption(filesFlag.rest, "--task");
|
|
8310
|
-
requireNoExtraArgs(remaining, "
|
|
8908
|
+
requireNoExtraArgs(remaining, "rig task scope [--task <id>] [--files]");
|
|
8311
8909
|
await withMutedConsole(context.outputMode === "json", () => taskScope(context.projectRoot, filesFlag.value, task || undefined));
|
|
8312
8910
|
return { ok: true, group: "task", command, details: { files: filesFlag.value, task: task || null } };
|
|
8313
8911
|
}
|
|
8314
8912
|
case "deps":
|
|
8315
|
-
requireNoExtraArgs(rest, "
|
|
8913
|
+
requireNoExtraArgs(rest, "rig task deps");
|
|
8316
8914
|
await withMutedConsole(context.outputMode === "json", () => taskDeps(context.projectRoot));
|
|
8317
8915
|
return { ok: true, group: "task", command };
|
|
8318
8916
|
case "status":
|
|
8319
|
-
requireNoExtraArgs(rest, "
|
|
8917
|
+
requireNoExtraArgs(rest, "rig task status");
|
|
8320
8918
|
withMutedConsole(context.outputMode === "json", () => taskStatus2(context.projectRoot));
|
|
8321
8919
|
return { ok: true, group: "task", command };
|
|
8322
8920
|
case "artifacts":
|
|
8323
|
-
requireNoExtraArgs(rest, "
|
|
8921
|
+
requireNoExtraArgs(rest, "rig task artifacts");
|
|
8324
8922
|
withMutedConsole(context.outputMode === "json", () => taskArtifacts(context.projectRoot));
|
|
8325
8923
|
return { ok: true, group: "task", command };
|
|
8326
8924
|
case "artifact-dir": {
|
|
8327
|
-
requireNoExtraArgs(rest, "
|
|
8925
|
+
requireNoExtraArgs(rest, "rig task artifact-dir");
|
|
8328
8926
|
const path = taskArtifactDir(context.projectRoot);
|
|
8329
8927
|
if (context.outputMode === "text") {
|
|
8330
8928
|
console.log(path);
|
|
@@ -8333,7 +8931,7 @@ async function executeTask(context, args, options) {
|
|
|
8333
8931
|
}
|
|
8334
8932
|
case "artifact-write": {
|
|
8335
8933
|
if (rest.length < 1) {
|
|
8336
|
-
throw new CliError2(`Usage:
|
|
8934
|
+
throw new CliError2(`Usage: rig task artifact-write <filename> [--file <path>]
|
|
8337
8935
|
` + ` Reads content from stdin (or --file), writes to the active task artifact dir.
|
|
8338
8936
|
` + " Example: echo '...' | rig task artifact-write collection-audit.md");
|
|
8339
8937
|
}
|
|
@@ -8346,7 +8944,7 @@ async function executeTask(context, args, options) {
|
|
|
8346
8944
|
content = await readStdin();
|
|
8347
8945
|
}
|
|
8348
8946
|
if (!artifactFilename) {
|
|
8349
|
-
throw new CliError2("Usage:
|
|
8947
|
+
throw new CliError2("Usage: rig task artifact-write <filename> [--file path]");
|
|
8350
8948
|
}
|
|
8351
8949
|
withMutedConsole(context.outputMode === "json", () => taskArtifactWrite(context.projectRoot, artifactFilename, content));
|
|
8352
8950
|
return { ok: true, group: "task", command, details: { filename: artifactFilename } };
|
|
@@ -8355,11 +8953,11 @@ async function executeTask(context, args, options) {
|
|
|
8355
8953
|
return options.executeTaskReportBug(context, rest);
|
|
8356
8954
|
case "lookup": {
|
|
8357
8955
|
if (rest.length !== 1) {
|
|
8358
|
-
throw new CliError2("Usage:
|
|
8956
|
+
throw new CliError2("Usage: rig task lookup <task-id>");
|
|
8359
8957
|
}
|
|
8360
8958
|
const lookupId = rest[0];
|
|
8361
8959
|
if (!lookupId) {
|
|
8362
|
-
throw new CliError2("Usage:
|
|
8960
|
+
throw new CliError2("Usage: rig task lookup <task-id>");
|
|
8363
8961
|
}
|
|
8364
8962
|
const result = taskLookup2(context.projectRoot, lookupId);
|
|
8365
8963
|
if (context.outputMode === "text") {
|
|
@@ -8369,17 +8967,17 @@ async function executeTask(context, args, options) {
|
|
|
8369
8967
|
}
|
|
8370
8968
|
case "record": {
|
|
8371
8969
|
if (rest.length < 2) {
|
|
8372
|
-
throw new CliError2("Usage:
|
|
8970
|
+
throw new CliError2("Usage: rig task record <decision|failure> <text>");
|
|
8373
8971
|
}
|
|
8374
8972
|
const type = rest[0];
|
|
8375
8973
|
if (type !== "decision" && type !== "failure") {
|
|
8376
|
-
throw new CliError2("Usage:
|
|
8974
|
+
throw new CliError2("Usage: rig task record <decision|failure> <text>");
|
|
8377
8975
|
}
|
|
8378
8976
|
withMutedConsole(context.outputMode === "json", () => taskRecord(context.projectRoot, type, rest.slice(1).join(" ")));
|
|
8379
8977
|
return { ok: true, group: "task", command, details: { type: rest[0] } };
|
|
8380
8978
|
}
|
|
8381
8979
|
case "ready":
|
|
8382
|
-
requireNoExtraArgs(rest, "
|
|
8980
|
+
requireNoExtraArgs(rest, "rig task ready");
|
|
8383
8981
|
await withMutedConsole(context.outputMode === "json", () => taskReady(context.projectRoot));
|
|
8384
8982
|
return { ok: true, group: "task", command };
|
|
8385
8983
|
case "run": {
|
|
@@ -8416,7 +9014,7 @@ async function executeTask(context, args, options) {
|
|
|
8416
9014
|
if (positionalTaskId) {
|
|
8417
9015
|
pending = pending.slice(1);
|
|
8418
9016
|
}
|
|
8419
|
-
requireNoExtraArgs(pending, "
|
|
9017
|
+
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]");
|
|
8420
9018
|
if (nextResult.value && (taskResult.value || positionalTaskId)) {
|
|
8421
9019
|
throw new CliError2("task run cannot combine --next with an explicit task id.", 2);
|
|
8422
9020
|
}
|
|
@@ -8470,10 +9068,24 @@ async function executeTask(context, args, options) {
|
|
|
8470
9068
|
});
|
|
8471
9069
|
let attachDetails = null;
|
|
8472
9070
|
if (!detachResult.value && context.outputMode === "text") {
|
|
8473
|
-
|
|
9071
|
+
printFormattedOutput(formatSubmittedRun({
|
|
9072
|
+
runId: submitted.runId,
|
|
9073
|
+
task: selectedTask ? summarizeTask(selectedTask) : null,
|
|
9074
|
+
runtimeAdapter,
|
|
9075
|
+
runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
|
|
9076
|
+
interactionMode: interactionModeResult.value || "default",
|
|
9077
|
+
detached: false
|
|
9078
|
+
}));
|
|
8474
9079
|
attachDetails = await attachRunOperatorView(context, { runId: submitted.runId, follow: true });
|
|
8475
9080
|
} else if (context.outputMode === "text") {
|
|
8476
|
-
|
|
9081
|
+
printFormattedOutput(formatSubmittedRun({
|
|
9082
|
+
runId: submitted.runId,
|
|
9083
|
+
task: selectedTask ? summarizeTask(selectedTask) : null,
|
|
9084
|
+
runtimeAdapter,
|
|
9085
|
+
runtimeMode: runtimeModeResult.value || projectDefaults.runtimeMode || "full-access",
|
|
9086
|
+
interactionMode: interactionModeResult.value || "default",
|
|
9087
|
+
detached: true
|
|
9088
|
+
}));
|
|
8477
9089
|
}
|
|
8478
9090
|
return {
|
|
8479
9091
|
ok: true,
|
|
@@ -8497,7 +9109,7 @@ async function executeTask(context, args, options) {
|
|
|
8497
9109
|
}
|
|
8498
9110
|
case "validate": {
|
|
8499
9111
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8500
|
-
requireNoExtraArgs(remaining, "
|
|
9112
|
+
requireNoExtraArgs(remaining, "rig task validate [--task <task-id>]");
|
|
8501
9113
|
if (context.dryRun) {
|
|
8502
9114
|
await context.runCommand(["rig", "task", "validate", ...task ? ["--task", task] : []]);
|
|
8503
9115
|
return { ok: true, group: "task", command, details: { task: task || "active" } };
|
|
@@ -8510,7 +9122,7 @@ async function executeTask(context, args, options) {
|
|
|
8510
9122
|
}
|
|
8511
9123
|
case "verify": {
|
|
8512
9124
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8513
|
-
requireNoExtraArgs(remaining, "
|
|
9125
|
+
requireNoExtraArgs(remaining, "rig task verify [--task <task-id>]");
|
|
8514
9126
|
if (context.dryRun) {
|
|
8515
9127
|
await context.runCommand(["rig", "task", "verify", ...task ? ["--task", task] : []]);
|
|
8516
9128
|
return { ok: true, group: "task", command, details: { task: task || "active" } };
|
|
@@ -8523,15 +9135,15 @@ async function executeTask(context, args, options) {
|
|
|
8523
9135
|
}
|
|
8524
9136
|
case "reset": {
|
|
8525
9137
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8526
|
-
requireNoExtraArgs(remaining, "
|
|
8527
|
-
const requiredTask = requireTask(task, "
|
|
9138
|
+
requireNoExtraArgs(remaining, "rig task reset --task <task-id>");
|
|
9139
|
+
const requiredTask = requireTask(task, "rig task reset --task <task-id>");
|
|
8528
9140
|
await context.runCommand(["br", "--no-db", "update", requiredTask, "--status", "open"]);
|
|
8529
9141
|
return { ok: true, group: "task", command, details: { task: requiredTask } };
|
|
8530
9142
|
}
|
|
8531
9143
|
case "details": {
|
|
8532
9144
|
const { value: task, rest: remaining } = takeOption(rest, "--task");
|
|
8533
|
-
requireNoExtraArgs(remaining, "
|
|
8534
|
-
const requiredTask = requireTask(task, "
|
|
9145
|
+
requireNoExtraArgs(remaining, "rig task details --task <task-id>");
|
|
9146
|
+
const requiredTask = requireTask(task, "rig task details --task <task-id>");
|
|
8535
9147
|
await withMutedConsole(context.outputMode === "json", () => taskInfo(context.projectRoot, requiredTask));
|
|
8536
9148
|
return { ok: true, group: "task", command, details: { task: requiredTask } };
|
|
8537
9149
|
}
|
|
@@ -8539,9 +9151,9 @@ async function executeTask(context, args, options) {
|
|
|
8539
9151
|
const { value: task, rest: rest1 } = takeOption(rest, "--task");
|
|
8540
9152
|
const allFlag = takeFlag(rest1, "--all");
|
|
8541
9153
|
const { rest: remaining } = takeOption(allFlag.rest, "--reason");
|
|
8542
|
-
requireNoExtraArgs(remaining, "
|
|
9154
|
+
requireNoExtraArgs(remaining, "rig task reopen [--task <id> | --all] [--reason <text>]");
|
|
8543
9155
|
if (!allFlag.value && !task) {
|
|
8544
|
-
throw new CliError2("Usage:
|
|
9156
|
+
throw new CliError2("Usage: rig task reopen [--task <id> | --all] [--reason <text>]");
|
|
8545
9157
|
}
|
|
8546
9158
|
const summary = withMutedConsole(context.outputMode === "json", () => taskReopen(context.projectRoot, {
|
|
8547
9159
|
all: allFlag.value,
|
|
@@ -10576,15 +11188,15 @@ async function executeTest(context, args) {
|
|
|
10576
11188
|
const [command = "unit", ...rest] = args;
|
|
10577
11189
|
switch (command) {
|
|
10578
11190
|
case "unit":
|
|
10579
|
-
requireNoExtraArgs(rest, "
|
|
11191
|
+
requireNoExtraArgs(rest, "rig test unit");
|
|
10580
11192
|
await context.runCommand(["bun", "test", "tests/harness/", "--ignore", "tests/harness/e2e/**"]);
|
|
10581
11193
|
return { ok: true, group: "test", command };
|
|
10582
11194
|
case "e2e":
|
|
10583
|
-
requireNoExtraArgs(rest, "
|
|
11195
|
+
requireNoExtraArgs(rest, "rig test e2e");
|
|
10584
11196
|
await context.runCommand(["bun", "test", "tests/harness/e2e/"]);
|
|
10585
11197
|
return { ok: true, group: "test", command };
|
|
10586
11198
|
case "all":
|
|
10587
|
-
requireNoExtraArgs(rest, "
|
|
11199
|
+
requireNoExtraArgs(rest, "rig test all");
|
|
10588
11200
|
await context.runCommand(["bun", "test", "tests/harness/"]);
|
|
10589
11201
|
return { ok: true, group: "test", command };
|
|
10590
11202
|
default:
|
|
@@ -10604,7 +11216,7 @@ async function executeSetup(context, args) {
|
|
|
10604
11216
|
const [command = "check", ...rest] = args;
|
|
10605
11217
|
switch (command) {
|
|
10606
11218
|
case "bootstrap":
|
|
10607
|
-
requireNoExtraArgs(rest, "
|
|
11219
|
+
requireNoExtraArgs(rest, "rig setup bootstrap");
|
|
10608
11220
|
{
|
|
10609
11221
|
const hostBash = Bun.which("bash") || "/bin/bash";
|
|
10610
11222
|
const env = { ...process.env };
|
|
@@ -10627,21 +11239,21 @@ async function executeSetup(context, args) {
|
|
|
10627
11239
|
}
|
|
10628
11240
|
return { ok: true, group: "setup", command };
|
|
10629
11241
|
case "check":
|
|
10630
|
-
requireNoExtraArgs(rest, `
|
|
11242
|
+
requireNoExtraArgs(rest, `rig setup ${command}`);
|
|
10631
11243
|
{
|
|
10632
11244
|
const checks = await withMutedConsole(context.outputMode === "json", () => runSetupCheck(context.projectRoot));
|
|
10633
11245
|
return { ok: true, group: "setup", command, details: { checks, failures: countDoctorFailures(checks) } };
|
|
10634
11246
|
}
|
|
10635
11247
|
case "setup":
|
|
10636
|
-
requireNoExtraArgs(rest, "
|
|
11248
|
+
requireNoExtraArgs(rest, "rig setup setup");
|
|
10637
11249
|
withMutedConsole(context.outputMode === "json", () => runSetupInit(context.projectRoot));
|
|
10638
11250
|
return { ok: true, group: "setup", command };
|
|
10639
11251
|
case "preflight":
|
|
10640
|
-
requireNoExtraArgs(rest, "
|
|
11252
|
+
requireNoExtraArgs(rest, "rig setup preflight");
|
|
10641
11253
|
await withMutedConsole(context.outputMode === "json", () => runSetupPreflight(context.projectRoot));
|
|
10642
11254
|
return { ok: true, group: "setup", command };
|
|
10643
11255
|
case "install-agent-shell":
|
|
10644
|
-
requireNoExtraArgs(rest, "
|
|
11256
|
+
requireNoExtraArgs(rest, "rig setup install-agent-shell");
|
|
10645
11257
|
if (context.outputMode === "text") {
|
|
10646
11258
|
console.log("install-agent-shell is deprecated. Runtime shells now use compiled rig-agent directly.");
|
|
10647
11259
|
}
|
|
@@ -10706,7 +11318,7 @@ async function executeWorkspace(context, args) {
|
|
|
10706
11318
|
const [command = "summary", ...rest] = args;
|
|
10707
11319
|
switch (command) {
|
|
10708
11320
|
case "summary": {
|
|
10709
|
-
requireNoExtraArgs(rest, "
|
|
11321
|
+
requireNoExtraArgs(rest, "rig workspace summary");
|
|
10710
11322
|
const summary = await readWorkspaceSummary(context.projectRoot);
|
|
10711
11323
|
if (context.outputMode === "text") {
|
|
10712
11324
|
console.log("Workspace Summary");
|
|
@@ -10731,7 +11343,7 @@ Warnings:`);
|
|
|
10731
11343
|
return { ok: true, group: "workspace", command, details: summary };
|
|
10732
11344
|
}
|
|
10733
11345
|
case "topology": {
|
|
10734
|
-
requireNoExtraArgs(rest, "
|
|
11346
|
+
requireNoExtraArgs(rest, "rig workspace topology");
|
|
10735
11347
|
const topology = readWorkspaceTopology(context.projectRoot);
|
|
10736
11348
|
if (context.outputMode === "text") {
|
|
10737
11349
|
console.log(`Topology: ${topology.status}`);
|
|
@@ -10744,7 +11356,7 @@ Warnings:`);
|
|
|
10744
11356
|
return { ok: true, group: "workspace", command, details: topology };
|
|
10745
11357
|
}
|
|
10746
11358
|
case "remote-hosts": {
|
|
10747
|
-
requireNoExtraArgs(rest, "
|
|
11359
|
+
requireNoExtraArgs(rest, "rig workspace remote-hosts");
|
|
10748
11360
|
const fleet = readWorkspaceRemoteFleet(context.projectRoot);
|
|
10749
11361
|
if (context.outputMode === "text") {
|
|
10750
11362
|
console.log(`Remote Hosts: ${fleet.status}`);
|
|
@@ -10759,7 +11371,7 @@ Warnings:`);
|
|
|
10759
11371
|
let pending = serviceRest;
|
|
10760
11372
|
const services = takeOption(pending, "--service");
|
|
10761
11373
|
pending = services.rest;
|
|
10762
|
-
requireNoExtraArgs(pending, "
|
|
11374
|
+
requireNoExtraArgs(pending, "rig workspace service-fabric <status|up|verify|down> [--service <name>]");
|
|
10763
11375
|
if (action !== "status" && action !== "up" && action !== "verify" && action !== "down") {
|
|
10764
11376
|
throw new CliError2(`Unknown workspace service-fabric action: ${action}`);
|
|
10765
11377
|
}
|
|
@@ -10780,200 +11392,6 @@ Warnings:`);
|
|
|
10780
11392
|
}
|
|
10781
11393
|
}
|
|
10782
11394
|
|
|
10783
|
-
// packages/cli/src/commands/_help-catalog.ts
|
|
10784
|
-
import pc4 from "picocolors";
|
|
10785
|
-
var PRIMARY_GROUPS = [
|
|
10786
|
-
{
|
|
10787
|
-
name: "init",
|
|
10788
|
-
summary: "Set up Rig for this repo: server, GitHub auth, checkout strategy, task source, and Pi wiring.",
|
|
10789
|
-
usage: ["rig init [--yes] [--server local|remote] [--repo owner/repo] [--remote-url <url>]"],
|
|
10790
|
-
commands: [
|
|
10791
|
-
{ command: "init", description: "Interactive setup wizard for a new or existing Rig repo.", primary: true },
|
|
10792
|
-
{ command: "init --yes", description: "Non-interactive setup using detected/default settings.", primary: true },
|
|
10793
|
-
{ command: "init --server remote --remote-url <url>", description: "Link this repo to a remote Rig server.", primary: true },
|
|
10794
|
-
{ command: "init --repair", description: "Repair missing private state without replacing project config." }
|
|
10795
|
-
],
|
|
10796
|
-
examples: [
|
|
10797
|
-
"rig init",
|
|
10798
|
-
"rig init --yes --repo humanity-org/humanwork",
|
|
10799
|
-
"rig init --server remote --remote-url https://where.rig-does.work --repo owner/repo"
|
|
10800
|
-
],
|
|
10801
|
-
next: ["After init, run `rig server status`.", "Then use `rig task list` and `rig task run --next` for day-to-day work."]
|
|
10802
|
-
},
|
|
10803
|
-
{
|
|
10804
|
-
name: "server",
|
|
10805
|
-
summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
|
|
10806
|
-
usage: ["rig server <status|list|add|use|start> [options]"],
|
|
10807
|
-
commands: [
|
|
10808
|
-
{ command: "status", description: "Show the selected server for this repo.", primary: true },
|
|
10809
|
-
{ command: "list", description: "List saved local/remote server aliases.", primary: true },
|
|
10810
|
-
{ command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
|
|
10811
|
-
{ command: "use [alias|local]", description: "Select a server; prompts in an interactive TTY.", primary: true },
|
|
10812
|
-
{ command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process.", primary: true }
|
|
10813
|
-
],
|
|
10814
|
-
examples: [
|
|
10815
|
-
"rig server status",
|
|
10816
|
-
"rig server add prod https://where.rig-does.work",
|
|
10817
|
-
"rig server use prod",
|
|
10818
|
-
"rig server use local",
|
|
10819
|
-
"rig server start --port 3773"
|
|
10820
|
-
],
|
|
10821
|
-
next: ["Use `rig task list` to see server-owned work.", "Use `rig run list` or `rig run attach <id> --follow` to monitor runs."],
|
|
10822
|
-
advanced: ["Compatibility alias: `rig connect ...` remains callable."]
|
|
10823
|
-
},
|
|
10824
|
-
{
|
|
10825
|
-
name: "task",
|
|
10826
|
-
summary: "Find work, start Pi-backed runs, and validate task results.",
|
|
10827
|
-
usage: ["rig task <list|next|show|run> [options]"],
|
|
10828
|
-
commands: [
|
|
10829
|
-
{ command: "list [--assignee <login|@me>] [--state open|closed]", description: "List tasks from the selected server/source.", primary: true },
|
|
10830
|
-
{ command: "next [filters]", description: "Pick the next matching task.", primary: true },
|
|
10831
|
-
{ command: "show <id>|--task <id>", description: "Show task details.", primary: true },
|
|
10832
|
-
{ command: "run [#<issue>|<task-id>|--next|--task <id>]", description: "Submit a task run; interactive follows with bundled Pi.", primary: true },
|
|
10833
|
-
{ command: "validate|verify [--task <id>]", description: "Run configured task checks/review gates." },
|
|
10834
|
-
{ command: "artifacts|artifact-dir|artifact-write", description: "Inspect or write task artifacts." },
|
|
10835
|
-
{ command: "report-bug", description: "Create a structured bug report/task." }
|
|
10836
|
-
],
|
|
10837
|
-
examples: [
|
|
10838
|
-
"rig task list --assignee @me --limit 20",
|
|
10839
|
-
"rig task run --next",
|
|
10840
|
-
"rig task run #123 --runtime-adapter pi",
|
|
10841
|
-
"rig task run --title 'Investigate deploy drift' --initial-prompt 'Check server health'"
|
|
10842
|
-
],
|
|
10843
|
-
next: ["Use `--detach` to submit without attaching.", "Use `rig run attach <run-id> --follow` to rejoin a live run."]
|
|
10844
|
-
},
|
|
10845
|
-
{
|
|
10846
|
-
name: "run",
|
|
10847
|
-
summary: "Observe, attach to, and control Rig runs.",
|
|
10848
|
-
usage: ["rig run <list|status|show|attach|stop> [options]"],
|
|
10849
|
-
commands: [
|
|
10850
|
-
{ command: "list", description: "List recent runs from the selected server or local state.", primary: true },
|
|
10851
|
-
{ command: "status", description: "Summarize active and recent runs.", primary: true },
|
|
10852
|
-
{ command: "show --run <id>", description: "Show one run record.", primary: true },
|
|
10853
|
-
{ command: "attach <run-id>|--run <id> [--follow]", description: "Attach to the run; `--follow` launches native bundled Pi for live Pi runs.", primary: true },
|
|
10854
|
-
{ command: "stop [<run-id>|--run <id>]", description: "Request stop for one run or local active runs.", primary: true },
|
|
10855
|
-
{ command: "timeline --run <id> [--follow]", description: "Stream raw run timeline events." },
|
|
10856
|
-
{ command: "delete|cleanup", description: "Remove completed run records/artifacts." }
|
|
10857
|
-
],
|
|
10858
|
-
examples: [
|
|
10859
|
-
"rig run list",
|
|
10860
|
-
"rig run attach 01234567-89ab-cdef-0123-456789abcdef --follow",
|
|
10861
|
-
"rig run show --run <run-id>",
|
|
10862
|
-
"rig run stop <run-id>"
|
|
10863
|
-
],
|
|
10864
|
-
next: ["Use `rig task run --next` to create a new run.", "Use `--json` when scripts need the full structured record."]
|
|
10865
|
-
}
|
|
10866
|
-
];
|
|
10867
|
-
var ADVANCED_GROUPS = [
|
|
10868
|
-
{ 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." }] },
|
|
10869
|
-
{ name: "github", summary: "GitHub auth helpers.", usage: ["rig github auth <status|import-gh|token>"], commands: [{ command: "auth status", description: "Show GitHub auth state." }] },
|
|
10870
|
-
{ name: "doctor", summary: "Diagnostics for project/server/GitHub/Pi state.", usage: ["rig doctor [check|run|shared|...]"], commands: [{ command: "check", description: "Run diagnostics." }] },
|
|
10871
|
-
{ name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
|
|
10872
|
-
{ 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." }] },
|
|
10873
|
-
{ name: "repo", summary: "Repository sync/baseline helpers.", usage: ["rig repo <sync|reset-baseline>"], commands: [{ command: "sync", description: "Sync project repository state." }] },
|
|
10874
|
-
{ name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
|
|
10875
|
-
{ name: "review", summary: "Review policy configuration.", usage: ["rig review <show|set>"], commands: [{ command: "show", description: "Show review settings." }] },
|
|
10876
|
-
{ name: "browser", summary: "Browser/app diagnostics.", usage: ["rig browser <help|explain|demo|app>"], commands: [{ command: "help", description: "Browser command help." }] },
|
|
10877
|
-
{ name: "plugin", summary: "Plugin validation/listing.", usage: ["rig plugin <list|validate>"], commands: [{ command: "list", description: "List plugins." }] },
|
|
10878
|
-
{ name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
|
|
10879
|
-
{ name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
|
|
10880
|
-
{ name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
|
|
10881
|
-
{ name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
|
|
10882
|
-
{ name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
|
|
10883
|
-
{ name: "remote", summary: "Legacy remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
|
|
10884
|
-
{ name: "inbox", summary: "Approval/input inbox for blocked runs.", usage: ["rig inbox <approvals|approve|inputs|respond>"], commands: [{ command: "approvals", description: "List pending approvals." }] },
|
|
10885
|
-
{ name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
|
|
10886
|
-
{ name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
|
|
10887
|
-
{ name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
|
|
10888
|
-
];
|
|
10889
|
-
var ALL_GROUPS = [...PRIMARY_GROUPS, ...ADVANCED_GROUPS];
|
|
10890
|
-
function heading(title) {
|
|
10891
|
-
return pc4.bold(pc4.cyan(title));
|
|
10892
|
-
}
|
|
10893
|
-
function commandLine(command, description) {
|
|
10894
|
-
const commandColumn = command.length >= 34 ? `${command} ` : command.padEnd(34);
|
|
10895
|
-
return `${pc4.dim("\u2502")} ${pc4.bold(commandColumn)} ${description}`;
|
|
10896
|
-
}
|
|
10897
|
-
function renderGroup(group) {
|
|
10898
|
-
const lines = [
|
|
10899
|
-
`${heading(`rig ${group.name}`)} \u2014 ${group.summary}`,
|
|
10900
|
-
"",
|
|
10901
|
-
pc4.bold("Usage"),
|
|
10902
|
-
...group.usage.map((line) => ` ${line}`),
|
|
10903
|
-
"",
|
|
10904
|
-
pc4.bold("Commands"),
|
|
10905
|
-
...group.commands.map((entry) => commandLine(entry.command, entry.description))
|
|
10906
|
-
];
|
|
10907
|
-
if (group.examples?.length) {
|
|
10908
|
-
lines.push("", pc4.bold("Examples"), ...group.examples.map((line) => ` ${pc4.dim("$")} ${line}`));
|
|
10909
|
-
}
|
|
10910
|
-
if (group.next?.length) {
|
|
10911
|
-
lines.push("", pc4.bold("Next steps"), ...group.next.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
10912
|
-
}
|
|
10913
|
-
if (group.advanced?.length) {
|
|
10914
|
-
lines.push("", pc4.bold("Compatibility / advanced"), ...group.advanced.map((line) => ` ${pc4.dim("\u203A")} ${line}`));
|
|
10915
|
-
}
|
|
10916
|
-
return lines.join(`
|
|
10917
|
-
`);
|
|
10918
|
-
}
|
|
10919
|
-
function renderTopLevelHelp() {
|
|
10920
|
-
return [
|
|
10921
|
-
`${heading("rig")} ${pc4.dim("\u2014 server-owned task/run control plane for Pi-backed engineering work")}`,
|
|
10922
|
-
pc4.dim("A repo-local CLI for setup, server selection, task runs, live attach, and completion review."),
|
|
10923
|
-
"",
|
|
10924
|
-
`${pc4.bold(pc4.magenta("\u25C7 Start here"))} \u2014 ${pc4.dim("bootstrap a repo and choose where Rig runs")}`,
|
|
10925
|
-
commandLine("rig init", "Interactive setup: project config, GitHub auth, task source, server, checkout, Pi."),
|
|
10926
|
-
commandLine("rig init --yes", "Non-interactive setup using detected defaults; good for repeatable installs."),
|
|
10927
|
-
commandLine("rig server status", "Show whether this repo is using local Rig or a remote server."),
|
|
10928
|
-
commandLine("rig server use <alias|local>", "Switch the server that owns task/run state for this repo."),
|
|
10929
|
-
"",
|
|
10930
|
-
`${pc4.bold(pc4.magenta("\u25C7 Daily task loop"))} \u2014 ${pc4.dim("find work, start a worker, and rejoin it later")}`,
|
|
10931
|
-
commandLine("rig task list", "List tasks from the selected task source/server with status, labels, and source."),
|
|
10932
|
-
commandLine("rig task next", "Pick the next matching task without starting it."),
|
|
10933
|
-
commandLine("rig task run --next", "Start the next task and attach to the live bundled Pi frontend."),
|
|
10934
|
-
commandLine("rig task run #123 --detach", "Submit a specific issue/task and return immediately."),
|
|
10935
|
-
"",
|
|
10936
|
-
`${pc4.bold(pc4.magenta("\u25C7 Live run control"))} \u2014 ${pc4.dim("observe, steer, stop, or inspect active runs")}`,
|
|
10937
|
-
commandLine("rig run list", "Show recent/active runs from the selected server or local state."),
|
|
10938
|
-
commandLine("rig run attach <run-id> --follow", "Open the native Pi live view for a worker-backed run."),
|
|
10939
|
-
commandLine("rig run show --run <id>", "Print one run record; add `--json` for automation."),
|
|
10940
|
-
commandLine("rig run stop <run-id>", "Request cancellation for a running worker."),
|
|
10941
|
-
"",
|
|
10942
|
-
`${pc4.bold(pc4.magenta("\u25C7 Core groups"))} \u2014 ${pc4.dim("run `rig <group> --help` for detailed commands and examples")}`,
|
|
10943
|
-
...PRIMARY_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
10944
|
-
commandLine("doctor", "Diagnose project/server/GitHub/task/Pi wiring when setup or runs misbehave."),
|
|
10945
|
-
"",
|
|
10946
|
-
`${pc4.bold(pc4.magenta("\u25C7 More"))}`,
|
|
10947
|
-
commandLine("rig help --advanced", "Legacy, dev, diagnostics, browser, queue, agent, remote, git, harness commands."),
|
|
10948
|
-
commandLine("rig <group> --help", "Rich per-group help with usage, descriptions, examples, and next steps."),
|
|
10949
|
-
commandLine("rig --version", "Print the installed Rig CLI version."),
|
|
10950
|
-
"",
|
|
10951
|
-
`${pc4.bold(pc4.magenta("\u25C7 Global options"))}`,
|
|
10952
|
-
commandLine("--project <path>", "Use a project root instead of auto-discovery."),
|
|
10953
|
-
commandLine("--json", "Emit structured output for scripts/agents."),
|
|
10954
|
-
commandLine("--dry-run", "Print the command plan without mutating state.")
|
|
10955
|
-
].join(`
|
|
10956
|
-
`);
|
|
10957
|
-
}
|
|
10958
|
-
function renderAdvancedHelp() {
|
|
10959
|
-
return [
|
|
10960
|
-
`${heading("rig advanced")} \u2014 legacy, dev, and compatibility groups`,
|
|
10961
|
-
"",
|
|
10962
|
-
pc4.bold("Primary groups are still"),
|
|
10963
|
-
" init, server, task, run",
|
|
10964
|
-
"",
|
|
10965
|
-
pc4.bold("Advanced groups"),
|
|
10966
|
-
...ADVANCED_GROUPS.map((group) => commandLine(group.name, group.summary)),
|
|
10967
|
-
"",
|
|
10968
|
-
pc4.dim("All groups remain callable. Prefer `rig server`, `rig task`, and `rig run` for day-to-day work.")
|
|
10969
|
-
].join(`
|
|
10970
|
-
`);
|
|
10971
|
-
}
|
|
10972
|
-
function renderGroupHelp(groupName) {
|
|
10973
|
-
const group = ALL_GROUPS.find((candidate) => candidate.name === groupName);
|
|
10974
|
-
return group ? renderGroup(group) : null;
|
|
10975
|
-
}
|
|
10976
|
-
|
|
10977
11395
|
// packages/cli/src/commands.ts
|
|
10978
11396
|
import { ensureProjectMainFreshBeforeRun as ensureProjectMainFreshBeforeRun2 } from "@rig/runtime/control-plane/project-main-pre-run-sync";
|
|
10979
11397
|
var TOP_LEVEL_ALIASES = {
|
|
@@ -10985,7 +11403,7 @@ var TOP_LEVEL_ALIASES = {
|
|
|
10985
11403
|
status: ["run", "status"],
|
|
10986
11404
|
start: ["task", "run", "--next"],
|
|
10987
11405
|
"start-parallel": ["run", "start-parallel"],
|
|
10988
|
-
"start-serial": ["
|
|
11406
|
+
"start-serial": ["run", "start-serial"],
|
|
10989
11407
|
resume: ["run", "resume"],
|
|
10990
11408
|
stop: ["run", "stop"],
|
|
10991
11409
|
ready: ["task", "ready"],
|
|
@@ -11041,7 +11459,7 @@ var GROUPS = new Set([
|
|
|
11041
11459
|
"test"
|
|
11042
11460
|
]);
|
|
11043
11461
|
function printGroupHelp(group) {
|
|
11044
|
-
|
|
11462
|
+
printGroupHelpDocument(group);
|
|
11045
11463
|
}
|
|
11046
11464
|
function isHelpArg(arg) {
|
|
11047
11465
|
return arg === "--help" || arg === "-h" || arg === "help";
|
|
@@ -11051,7 +11469,7 @@ function helpText() {
|
|
|
11051
11469
|
}
|
|
11052
11470
|
async function execute(context, args) {
|
|
11053
11471
|
if (args.length === 0) {
|
|
11054
|
-
|
|
11472
|
+
printTopLevelHelp();
|
|
11055
11473
|
return { ok: true, group: "help", command: "show" };
|
|
11056
11474
|
}
|
|
11057
11475
|
const [first, ...rest] = args;
|
|
@@ -11062,14 +11480,14 @@ ${helpText()}`);
|
|
|
11062
11480
|
}
|
|
11063
11481
|
if (first === "help" || first === "--help" || first === "-h") {
|
|
11064
11482
|
if (rest[0] === "--advanced") {
|
|
11065
|
-
|
|
11483
|
+
printAdvancedHelp();
|
|
11066
11484
|
return { ok: true, group: "help", command: "advanced" };
|
|
11067
11485
|
}
|
|
11068
11486
|
if (rest[0]) {
|
|
11069
|
-
|
|
11487
|
+
printGroupHelp(rest[0]);
|
|
11070
11488
|
return { ok: true, group: "help", command: rest[0] };
|
|
11071
11489
|
}
|
|
11072
|
-
|
|
11490
|
+
printTopLevelHelp();
|
|
11073
11491
|
return { ok: true, group: "help", command: "show" };
|
|
11074
11492
|
}
|
|
11075
11493
|
if (first === "--version" || first === "-V" || first === "version") {
|