@h-rig/cli 0.0.6-alpha.9 → 0.0.6-alpha.90

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.
Files changed (114) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/build-rig-binaries.d.ts +2 -0
  3. package/dist/bin/rig.d.ts +2 -0
  4. package/dist/bin/rig.js +11052 -6668
  5. package/dist/src/app/board.d.ts +23 -0
  6. package/dist/src/app/board.js +1786 -0
  7. package/dist/src/app/drone-ui.d.ts +37 -0
  8. package/dist/src/app/drone-ui.js +294 -0
  9. package/dist/src/app/theme.d.ts +47 -0
  10. package/dist/src/app/theme.js +150 -0
  11. package/dist/src/commands/_async-ui.d.ts +13 -0
  12. package/dist/src/commands/_async-ui.js +223 -0
  13. package/dist/src/commands/_authority-runs.d.ts +22 -0
  14. package/dist/src/commands/_authority-runs.js +2 -3
  15. package/dist/src/commands/_cli-format.d.ts +49 -0
  16. package/dist/src/commands/_cli-format.js +447 -0
  17. package/dist/src/commands/_connection-state.d.ts +44 -0
  18. package/dist/src/commands/_connection-state.js +30 -11
  19. package/dist/src/commands/_doctor-checks.d.ts +52 -0
  20. package/dist/src/commands/_doctor-checks.js +180 -44
  21. package/dist/src/commands/_help-catalog.d.ts +51 -0
  22. package/dist/src/commands/_help-catalog.js +442 -0
  23. package/dist/src/commands/_json-output.d.ts +11 -0
  24. package/dist/src/commands/_json-output.js +56 -0
  25. package/dist/src/commands/_operator-surface.d.ts +34 -0
  26. package/dist/src/commands/_operator-surface.js +220 -0
  27. package/dist/src/commands/_operator-view.d.ts +30 -0
  28. package/dist/src/commands/_operator-view.js +803 -73
  29. package/dist/src/commands/_parsers.d.ts +15 -0
  30. package/dist/src/commands/_parsers.js +18 -11
  31. package/dist/src/commands/_paths.d.ts +11 -0
  32. package/dist/src/commands/_pi-frontend.d.ts +27 -0
  33. package/dist/src/commands/_pi-frontend.js +742 -0
  34. package/dist/src/commands/_pi-install.d.ts +42 -0
  35. package/dist/src/commands/_pi-install.js +5 -4
  36. package/dist/src/commands/_policy.d.ts +8 -0
  37. package/dist/src/commands/_policy.js +12 -5
  38. package/dist/src/commands/_preflight.d.ts +22 -0
  39. package/dist/src/commands/_preflight.js +190 -128
  40. package/dist/src/commands/_probes.d.ts +1 -0
  41. package/dist/src/commands/_run-driver-helpers.d.ts +99 -0
  42. package/dist/src/commands/_run-driver-helpers.js +75 -22
  43. package/dist/src/commands/_run-replay.d.ts +24 -0
  44. package/dist/src/commands/_run-replay.js +142 -0
  45. package/dist/src/commands/_server-client.d.ts +186 -0
  46. package/dist/src/commands/_server-client.js +360 -61
  47. package/dist/src/commands/_snapshot-upload.d.ts +39 -0
  48. package/dist/src/commands/_snapshot-upload.js +163 -39
  49. package/dist/src/commands/_spinner.d.ts +25 -0
  50. package/dist/src/commands/_spinner.js +65 -0
  51. package/dist/src/commands/_task-picker.d.ts +9 -0
  52. package/dist/src/commands/_task-picker.js +172 -19
  53. package/dist/src/commands/agent.d.ts +3 -0
  54. package/dist/src/commands/agent.js +39 -20
  55. package/dist/src/commands/browser.d.ts +65 -0
  56. package/dist/src/commands/browser.js +334 -51
  57. package/dist/src/commands/connect.d.ts +7 -0
  58. package/dist/src/commands/connect.js +272 -33
  59. package/dist/src/commands/dist.d.ts +28 -0
  60. package/dist/src/commands/dist.js +19 -12
  61. package/dist/src/commands/doctor.d.ts +3 -0
  62. package/dist/src/commands/doctor.js +378 -45
  63. package/dist/src/commands/github.d.ts +3 -0
  64. package/dist/src/commands/github.js +375 -53
  65. package/dist/src/commands/inbox.d.ts +30 -0
  66. package/dist/src/commands/inbox.js +760 -70
  67. package/dist/src/commands/init.d.ts +74 -0
  68. package/dist/src/commands/init.js +963 -119
  69. package/dist/src/commands/inspect.d.ts +3 -0
  70. package/dist/src/commands/inspect.js +588 -32
  71. package/dist/src/commands/inspector.d.ts +3 -0
  72. package/dist/src/commands/inspector.js +20 -13
  73. package/dist/src/commands/pi.d.ts +3 -0
  74. package/dist/src/commands/pi.js +177 -0
  75. package/dist/src/commands/plugin.d.ts +16 -0
  76. package/dist/src/commands/plugin.js +95 -27
  77. package/dist/src/commands/profile-and-review.d.ts +4 -0
  78. package/dist/src/commands/profile-and-review.js +26 -19
  79. package/dist/src/commands/queue.d.ts +3 -0
  80. package/dist/src/commands/queue.js +32 -12
  81. package/dist/src/commands/remote.d.ts +3 -0
  82. package/dist/src/commands/remote.js +43 -36
  83. package/dist/src/commands/repo-git-harness.d.ts +5 -0
  84. package/dist/src/commands/repo-git-harness.js +22 -15
  85. package/dist/src/commands/run.d.ts +3 -0
  86. package/dist/src/commands/run.js +1379 -159
  87. package/dist/src/commands/server.d.ts +7 -0
  88. package/dist/src/commands/server.js +502 -57
  89. package/dist/src/commands/setup.d.ts +16 -0
  90. package/dist/src/commands/setup.js +390 -63
  91. package/dist/src/commands/stats.d.ts +12 -0
  92. package/dist/src/commands/stats.js +1051 -0
  93. package/dist/src/commands/task-report-bug.d.ts +19 -0
  94. package/dist/src/commands/task-report-bug.js +260 -62
  95. package/dist/src/commands/task-run-driver.d.ts +132 -0
  96. package/dist/src/commands/task-run-driver.js +886 -130
  97. package/dist/src/commands/task.d.ts +14 -0
  98. package/dist/src/commands/task.js +1644 -314
  99. package/dist/src/commands/test.d.ts +3 -0
  100. package/dist/src/commands/test.js +15 -8
  101. package/dist/src/commands/workspace.d.ts +3 -0
  102. package/dist/src/commands/workspace.js +18 -11
  103. package/dist/src/commands.d.ts +29 -0
  104. package/dist/src/commands.js +10967 -6637
  105. package/dist/src/index.d.ts +4 -0
  106. package/dist/src/index.js +10168 -5787
  107. package/dist/src/launcher.d.ts +61 -0
  108. package/dist/src/launcher.js +77 -13
  109. package/dist/src/report-bug.d.ts +44 -0
  110. package/dist/src/report-bug.js +3 -3
  111. package/dist/src/runner.d.ts +47 -0
  112. package/dist/src/runner.js +16 -22
  113. package/dist/src/withMutedConsole.d.ts +2 -0
  114. package/package.json +13 -6
@@ -1,12 +1,19 @@
1
1
  // @bun
2
2
  // packages/cli/src/runner.ts
3
3
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
4
- import { CliError } from "@rig/runtime/control-plane/errors";
4
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
5
5
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
6
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
7
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
8
6
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
9
- import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
7
+
8
+ class CliError extends RuntimeCliError {
9
+ hint;
10
+ constructor(message, exitCode = 1, options = {}) {
11
+ super(message, exitCode);
12
+ if (options.hint?.trim()) {
13
+ this.hint = options.hint.trim();
14
+ }
15
+ }
16
+ }
10
17
  function takeFlag(args, flag) {
11
18
  const rest = [];
12
19
  let value = false;
@@ -27,7 +34,7 @@ function takeOption(args, option) {
27
34
  if (current === option) {
28
35
  const next = args[index + 1];
29
36
  if (!next || next.startsWith("-")) {
30
- throw new CliError(`Missing value for ${option}`);
37
+ throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
31
38
  }
32
39
  value = next;
33
40
  index += 1;
@@ -56,7 +63,7 @@ function parsePositiveInt(value, option, fallback) {
56
63
  }
57
64
  const parsed = Number.parseInt(value, 10);
58
65
  if (!Number.isFinite(parsed) || parsed <= 0) {
59
- throw new CliError2(`Invalid ${option} value: ${value}`);
66
+ throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
60
67
  }
61
68
  return parsed;
62
69
  }
@@ -70,7 +77,7 @@ function parseAction(value) {
70
77
  if (value === "pipeline") {
71
78
  return "pipeline";
72
79
  }
73
- throw new CliError2(`Invalid --action value: ${value}. Use validate, verify, or pipeline.`);
80
+ throw new CliError(`Invalid --action value: ${value}. Use validate, verify, or pipeline.`);
74
81
  }
75
82
  function parseIsolationMode(value, allowOff) {
76
83
  if (!value) {
@@ -82,7 +89,7 @@ function parseIsolationMode(value, allowOff) {
82
89
  if (allowOff && value === "off") {
83
90
  return value;
84
91
  }
85
- throw new CliError2(`Invalid isolation mode: ${value}. Use ${allowOff ? "off|" : ""}worktree.`);
92
+ throw new CliError(`Invalid isolation mode: ${value}. Use ${allowOff ? "off|" : ""}worktree.`);
86
93
  }
87
94
 
88
95
  // packages/cli/src/commands/_preflight.ts
@@ -90,6 +97,19 @@ import { ensureProjectMainFreshBeforeRun } from "@rig/runtime/control-plane/proj
90
97
 
91
98
  // packages/cli/src/commands/_server-client.ts
92
99
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
100
+ var scopedGitHubBearerTokens = new Map;
101
+ var serverReachabilityCache = new Map;
102
+ var RESUMABLE_RUN_STATUSES = new Set([
103
+ "created",
104
+ "preparing",
105
+ "running",
106
+ "validating",
107
+ "reviewing",
108
+ "stopped",
109
+ "failed",
110
+ "needs-attention",
111
+ "needs_attention"
112
+ ]);
93
113
 
94
114
  // packages/cli/src/commands/_preflight.ts
95
115
  async function runProjectMainSyncPreflight(context, options) {
@@ -105,7 +125,7 @@ async function runProjectMainSyncPreflight(context, options) {
105
125
  runBootstrap: async () => {
106
126
  const bootstrap = await context.runCommand(["bun", "run", "bootstrap"]);
107
127
  if (bootstrap.exitCode !== 0) {
108
- throw new CliError2(bootstrap.stderr || bootstrap.stdout || "bun run bootstrap failed during project pre-run sync", bootstrap.exitCode || 1);
128
+ throw new CliError(bootstrap.stderr || bootstrap.stdout || "bun run bootstrap failed during project pre-run sync", bootstrap.exitCode || 1);
109
129
  }
110
130
  }
111
131
  });
@@ -150,7 +170,7 @@ async function executeQueue(context, args) {
150
170
  pending = failFastResult.rest;
151
171
  const skipProjectSyncResult = takeFlag(pending, "--skip-project-sync");
152
172
  pending = skipProjectSyncResult.rest;
153
- requireNoExtraArgs(pending, "bun run rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]");
173
+ 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]");
154
174
  const workers = parsePositiveInt(workersResult.value, "--workers", 2);
155
175
  const maxTasks = parsePositiveInt(maxTasksResult.value, "--max-tasks", 10);
156
176
  const action = parseAction(actionResult.value);
@@ -171,7 +191,7 @@ async function executeQueue(context, args) {
171
191
  console.log(`Failed: ${summary.failed}`);
172
192
  }
173
193
  if (summary.failed > 0) {
174
- throw new CliError2(`Queue finished with ${summary.failed} failed task(s).`, 3);
194
+ throw new CliError(`Queue finished with ${summary.failed} failed task(s).`, 3, { hint: "Inspect the failures with `rig inspect failures`, then re-run `rig queue run`." });
175
195
  }
176
196
  return {
177
197
  ok: true,
@@ -189,7 +209,7 @@ async function executeQueue(context, args) {
189
209
  };
190
210
  }
191
211
  default:
192
- throw new CliError2(`Unknown queue command: ${command}`);
212
+ throw new CliError(`Unknown queue command: ${command}`, 1, { hint: "Run `rig queue --help` \u2014 the primary command is `rig queue run`." });
193
213
  }
194
214
  }
195
215
  export {
@@ -0,0 +1,3 @@
1
+ import { type RunnerContext } from "../runner";
2
+ import type { CommandOutcome } from "@rig/runtime/control-plane/runtime/types";
3
+ export declare function executeRemote(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
@@ -1,12 +1,19 @@
1
1
  // @bun
2
2
  // packages/cli/src/runner.ts
3
3
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
4
- import { CliError } from "@rig/runtime/control-plane/errors";
4
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
5
5
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
6
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
7
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
8
6
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
9
- import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
7
+
8
+ class CliError extends RuntimeCliError {
9
+ hint;
10
+ constructor(message, exitCode = 1, options = {}) {
11
+ super(message, exitCode);
12
+ if (options.hint?.trim()) {
13
+ this.hint = options.hint.trim();
14
+ }
15
+ }
16
+ }
10
17
  function takeFlag(args, flag) {
11
18
  const rest = [];
12
19
  let value = false;
@@ -27,7 +34,7 @@ function takeOption(args, option) {
27
34
  if (current === option) {
28
35
  const next = args[index + 1];
29
36
  if (!next || next.startsWith("-")) {
30
- throw new CliError(`Missing value for ${option}`);
37
+ throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
31
38
  }
32
39
  value = next;
33
40
  index += 1;
@@ -75,17 +82,17 @@ function parseOptionalPositiveInt(value, option) {
75
82
  }
76
83
  const parsed = Number.parseInt(value, 10);
77
84
  if (!Number.isFinite(parsed) || parsed <= 0) {
78
- throw new CliError2(`Invalid ${option} value: ${value}`);
85
+ throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
79
86
  }
80
87
  return parsed;
81
88
  }
82
89
  function parseRequiredPositiveInt(value, option) {
83
90
  if (!value) {
84
- throw new CliError2(`Missing value for ${option}.`);
91
+ throw new CliError(`Missing value for ${option}.`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} 10\`.` });
85
92
  }
86
93
  const parsed = Number.parseInt(value, 10);
87
94
  if (!Number.isFinite(parsed) || parsed <= 0) {
88
- throw new CliError2(`Invalid ${option} value: ${value}`);
95
+ throw new CliError(`Invalid ${option} value: ${value}`, 1, { hint: `Pass a positive integer, e.g. \`${option} 10\`.` });
89
96
  }
90
97
  return parsed;
91
98
  }
@@ -134,7 +141,7 @@ async function executeRemote(context, args) {
134
141
  const [subcommand = "list", ...subRest] = rest;
135
142
  switch (subcommand) {
136
143
  case "list": {
137
- requireNoExtraArgs(subRest, "bun run rig remote endpoint list");
144
+ requireNoExtraArgs(subRest, "rig remote endpoint list");
138
145
  const endpoints = listManagedRemoteEndpoints(undefined, context.projectRoot);
139
146
  const redactedEndpoints = endpoints.map((endpoint2) => redactRemoteEndpoint(endpoint2));
140
147
  if (context.outputMode === "text") {
@@ -158,9 +165,9 @@ async function executeRemote(context, args) {
158
165
  pending2 = port.rest;
159
166
  const token = takeOption(pending2, "--token");
160
167
  pending2 = token.rest;
161
- requireNoExtraArgs(pending2, "bun run rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
168
+ requireNoExtraArgs(pending2, "rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>");
162
169
  if (!alias.value || !host.value || !token.value || !port.value) {
163
- throw new CliError2("remote endpoint add requires --alias, --host, --port, and --token.");
170
+ throw new CliError("remote endpoint add requires --alias, --host, --port, and --token.", 1, { hint: "Re-run as `rig remote endpoint add --alias <a> --host <h> --port <n> --token <t>`." });
164
171
  }
165
172
  const created = upsertManagedRemoteEndpoint({
166
173
  alias: alias.value,
@@ -185,9 +192,9 @@ async function executeRemote(context, args) {
185
192
  pending2 = port.rest;
186
193
  const token = takeOption(pending2, "--token");
187
194
  pending2 = token.rest;
188
- requireNoExtraArgs(pending2, "bun run rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
195
+ requireNoExtraArgs(pending2, "rig remote endpoint update --id <id> [--alias <a>] [--host <h>] [--port <n>] [--token <t>]");
189
196
  if (!endpointId.value && !alias.value) {
190
- throw new CliError2("remote endpoint update requires --id <id> or --alias <a>.");
197
+ throw new CliError("remote endpoint update requires --id <id> or --alias <a>.", 1, { hint: "List endpoints with `rig remote endpoint list`, then pass --id or --alias." });
191
198
  }
192
199
  const updated = updateManagedRemoteEndpointInAuthority(context.projectRoot, {
193
200
  endpointId: endpointId.value || undefined,
@@ -197,7 +204,7 @@ async function executeRemote(context, args) {
197
204
  token: token.value || undefined
198
205
  });
199
206
  if (!updated) {
200
- throw new CliError2("Remote endpoint not found.", 2);
207
+ throw new CliError("Remote endpoint not found.", 2, { hint: "Run `rig remote endpoint list` to see configured endpoints." });
201
208
  }
202
209
  if (context.outputMode === "text") {
203
210
  console.log(`Updated remote endpoint ${updated.alias} -> ${updated.host}:${updated.port}`);
@@ -208,13 +215,13 @@ async function executeRemote(context, args) {
208
215
  let pending2 = subRest;
209
216
  const alias = takeOption(pending2, "--alias");
210
217
  pending2 = alias.rest;
211
- requireNoExtraArgs(pending2, "bun run rig remote endpoint remove --alias <a>");
218
+ requireNoExtraArgs(pending2, "rig remote endpoint remove --alias <a>");
212
219
  if (!alias.value) {
213
- throw new CliError2("remote endpoint remove requires --alias.");
220
+ throw new CliError("remote endpoint remove requires --alias.", 1, { hint: "Run `rig remote endpoint list` to find the alias, then `rig remote endpoint remove --alias <a>`." });
214
221
  }
215
222
  const removed = removeManagedRemoteEndpoint(alias.value, undefined, context.projectRoot);
216
223
  if (!removed) {
217
- throw new CliError2(`Remote endpoint alias not found: ${alias.value}`, 2);
224
+ throw new CliError(`Remote endpoint alias not found: ${alias.value}`, 2, { hint: "Run `rig remote endpoint list` to see configured endpoint aliases." });
218
225
  }
219
226
  if (context.outputMode === "text") {
220
227
  console.log(`Removed remote endpoint ${alias.value}`);
@@ -225,9 +232,9 @@ async function executeRemote(context, args) {
225
232
  let pending2 = subRest;
226
233
  const alias = takeOption(pending2, "--alias");
227
234
  pending2 = alias.rest;
228
- requireNoExtraArgs(pending2, "bun run rig remote endpoint test --alias <a>");
235
+ requireNoExtraArgs(pending2, "rig remote endpoint test --alias <a>");
229
236
  if (!alias.value) {
230
- throw new CliError2("remote endpoint test requires --alias.");
237
+ throw new CliError("remote endpoint test requires --alias.", 1, { hint: "Run `rig remote endpoint list` to find the alias, then `rig remote endpoint test --alias <a>`." });
231
238
  }
232
239
  const endpoint2 = resolveRemoteEndpoint({ remoteAlias: alias.value, projectRoot: context.projectRoot });
233
240
  const client = new RemoteWsClient(endpoint2);
@@ -256,7 +263,7 @@ async function executeRemote(context, args) {
256
263
  }
257
264
  }
258
265
  case "migrate": {
259
- requireNoExtraArgs(subRest, "bun run rig remote endpoint migrate");
266
+ requireNoExtraArgs(subRest, "rig remote endpoint migrate");
260
267
  const result = migrateManagedRemoteEndpoints(context.projectRoot);
261
268
  if (context.outputMode === "text") {
262
269
  console.log(`Imported ${result.imported} endpoint(s) from ${result.sourcePath}${result.skipped > 0 ? `, skipped ${result.skipped}` : ""}.`);
@@ -264,7 +271,7 @@ async function executeRemote(context, args) {
264
271
  return { ok: true, group: "remote", command: "endpoint migrate", details: result };
265
272
  }
266
273
  case "doctor": {
267
- requireNoExtraArgs(subRest, "bun run rig remote endpoint doctor");
274
+ requireNoExtraArgs(subRest, "rig remote endpoint doctor");
268
275
  const result = doctorManagedRemoteEndpoints(context.projectRoot);
269
276
  if (context.outputMode === "text") {
270
277
  console.log(JSON.stringify(result, null, 2));
@@ -272,7 +279,7 @@ async function executeRemote(context, args) {
272
279
  return { ok: true, group: "remote", command: "endpoint doctor", details: result };
273
280
  }
274
281
  default:
275
- throw new CliError2(`Unknown remote endpoint command: ${subcommand}`);
282
+ throw new CliError(`Unknown remote endpoint command: ${subcommand}`, 1, { hint: "Run `rig remote --help` for endpoint commands (list|add|update|remove|test)." });
276
283
  }
277
284
  }
278
285
  let pending = rest;
@@ -317,17 +324,17 @@ async function executeRemote(context, args) {
317
324
  try {
318
325
  switch (command) {
319
326
  case "test": {
320
- requireNoExtraArgs(pending, "bun run rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
327
+ requireNoExtraArgs(pending, "rig remote test [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
321
328
  const response = await withClient((client) => client.ping());
322
329
  return { ok: true, group: "remote", command, details: toDetails(response) };
323
330
  }
324
331
  case "status": {
325
- requireNoExtraArgs(pending, "bun run rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
332
+ requireNoExtraArgs(pending, "rig remote status [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
326
333
  const response = await withClient((client) => client.getState());
327
334
  return { ok: true, group: "remote", command, details: toDetails(response) };
328
335
  }
329
336
  case "tasks": {
330
- requireNoExtraArgs(pending, "bun run rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
337
+ requireNoExtraArgs(pending, "rig remote tasks [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
331
338
  const response = await withClient((client) => client.getTasks());
332
339
  return { ok: true, group: "remote", command, details: toDetails(response) };
333
340
  }
@@ -337,11 +344,11 @@ async function executeRemote(context, args) {
337
344
  watchPending = secondsResult.rest;
338
345
  const eventResult = takeOption(watchPending, "--event");
339
346
  watchPending = eventResult.rest;
340
- requireNoExtraArgs(watchPending, "bun run rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
347
+ requireNoExtraArgs(watchPending, "rig remote watch [--seconds <n>] [--event <type>] [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]");
341
348
  const seconds = parseOptionalPositiveInt(secondsResult.value, "--seconds");
342
349
  const eventFilter = eventResult.value || undefined;
343
350
  if (context.outputMode === "json" && !seconds) {
344
- throw new CliError2("--json remote watch requires --seconds <n> to produce bounded output.", 2);
351
+ throw new CliError("--json remote watch requires --seconds <n> to produce bounded output.", 2, { hint: "Re-run as `rig remote watch --seconds 10 --json`." });
345
352
  }
346
353
  const captured = [];
347
354
  let dropped = 0;
@@ -406,7 +413,7 @@ async function executeRemote(context, args) {
406
413
  case "stop":
407
414
  case "continue":
408
415
  case "refresh": {
409
- requireNoExtraArgs(pending, `bun run rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
416
+ requireNoExtraArgs(pending, `rig remote ${command} [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
410
417
  const response = await withClient(async (client) => {
411
418
  switch (command) {
412
419
  case "pause":
@@ -429,7 +436,7 @@ async function executeRemote(context, args) {
429
436
  let countPending = pending;
430
437
  const countResult = takeOption(countPending, "--count");
431
438
  countPending = countResult.rest;
432
- requireNoExtraArgs(countPending, `bun run rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
439
+ requireNoExtraArgs(countPending, `rig remote ${command} --count <n> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
433
440
  const count = parseRequiredPositiveInt(countResult.value, "--count");
434
441
  const response = await withClient(async (client) => command === "add-iterations" ? await client.addIterations(count) : await client.removeIterations(count));
435
442
  assertRemoteOperationSuccess(command, response);
@@ -440,8 +447,8 @@ async function executeRemote(context, args) {
440
447
  let taskPending = pending;
441
448
  const taskResult = takeOption(taskPending, "--task");
442
449
  taskPending = taskResult.rest;
443
- requireNoExtraArgs(taskPending, `bun run rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
444
- const taskId = requireTask(taskResult.value, `bun run rig remote ${command} --task <id>`);
450
+ requireNoExtraArgs(taskPending, `rig remote ${command} --task <id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
451
+ const taskId = requireTask(taskResult.value, `rig remote ${command} --task <id>`);
445
452
  const response = await withClient(async (client) => command === "prompt-preview" ? await client.getPromptPreview(taskId) : await client.getIterationOutput(taskId));
446
453
  assertRemoteOperationSuccess(command, response);
447
454
  return { ok: true, group: "remote", command, details: toDetails(response) };
@@ -454,7 +461,7 @@ async function executeRemote(context, args) {
454
461
  orchestrationPending = maxIterationsResult.rest;
455
462
  const directMergeResult = takeFlag(orchestrationPending, "--direct-merge");
456
463
  orchestrationPending = directMergeResult.rest;
457
- requireNoExtraArgs(orchestrationPending, "bun run rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
464
+ requireNoExtraArgs(orchestrationPending, "rig remote orchestrate-start [--max-workers <n>] [--max-iterations <n>] [--direct-merge]");
458
465
  const response = await withClient((client) => client.startOrchestration({
459
466
  maxWorkers: parseOptionalPositiveInt(maxWorkersResult.value, "--max-workers"),
460
467
  maxIterations: parseOptionalPositiveInt(maxIterationsResult.value, "--max-iterations"),
@@ -475,8 +482,8 @@ async function executeRemote(context, args) {
475
482
  let orchestrationPending = pending;
476
483
  const idResult = takeOption(orchestrationPending, "--id");
477
484
  orchestrationPending = idResult.rest;
478
- requireNoExtraArgs(orchestrationPending, `bun run rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
479
- const orchestrationId = requireTask(idResult.value, `bun run rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
485
+ requireNoExtraArgs(orchestrationPending, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
486
+ const orchestrationId = requireTask(idResult.value, `rig remote ${command} --id <orch-id> [--remote <alias>] [--host <host>] [--port <n>] [--token <token>]`);
480
487
  const response = await withClient(async (client) => {
481
488
  switch (command) {
482
489
  case "orchestrate-pause":
@@ -493,11 +500,11 @@ async function executeRemote(context, args) {
493
500
  return { ok: true, group: "remote", command, details: toDetails(response) };
494
501
  }
495
502
  default:
496
- throw new CliError2(`Unknown remote command: ${command}`);
503
+ throw new CliError(`Unknown remote command: ${command}`, 1, { hint: "Run `rig remote --help` to list remote commands." });
497
504
  }
498
505
  } catch (error) {
499
506
  if (error instanceof RemoteCliError) {
500
- throw new CliError2(`[${error.code}] ${error.message}`, error.exitCode);
507
+ throw new CliError(`[${error.code}] ${error.message}`, error.exitCode);
501
508
  }
502
509
  throw error;
503
510
  }
@@ -0,0 +1,5 @@
1
+ import { type RunnerContext } from "../runner";
2
+ import type { CommandOutcome } from "@rig/runtime/control-plane/runtime/types";
3
+ export declare function executeRepo(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
4
+ export declare function executeGit(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
5
+ export declare function executeHarness(context: RunnerContext, args: string[]): Promise<CommandOutcome>;
@@ -1,12 +1,19 @@
1
1
  // @bun
2
2
  // packages/cli/src/runner.ts
3
3
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
4
- import { CliError } from "@rig/runtime/control-plane/errors";
4
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
5
5
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
6
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
7
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
8
6
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
9
- import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
7
+
8
+ class CliError extends RuntimeCliError {
9
+ hint;
10
+ constructor(message, exitCode = 1, options = {}) {
11
+ super(message, exitCode);
12
+ if (options.hint?.trim()) {
13
+ this.hint = options.hint.trim();
14
+ }
15
+ }
16
+ }
10
17
  function formatCommand(parts) {
11
18
  return parts.map((part) => /[^a-zA-Z0-9_./:-]/.test(part) ? JSON.stringify(part) : part).join(" ");
12
19
  }
@@ -30,7 +37,7 @@ function takeOption(args, option) {
30
37
  if (current === option) {
31
38
  const next = args[index + 1];
32
39
  if (!next || next.startsWith("-")) {
33
- throw new CliError(`Missing value for ${option}`);
40
+ throw new CliError(`Missing value for ${option}`, 1, { hint: `Provide a value after ${option}, e.g. \`${option} <value>\`.` });
34
41
  }
35
42
  value = next;
36
43
  index += 1;
@@ -148,7 +155,7 @@ async function enforceNativeCommandPolicy(context, args, options) {
148
155
  appendControlledBashAudit(context, mode, command, args, matchedRuleIds, action === "block" ? "blocked" : action === "warn" ? "warn" : undefined);
149
156
  }
150
157
  if (action === "block") {
151
- throw new CliError2(`Policy blocked command: ${command}`, 126);
158
+ throw new CliError(`Policy blocked command: ${command}`, 126, { hint: "Review rig/policy/policy.json, or re-run with `--policy-mode observe` to log instead of block." });
152
159
  }
153
160
  }
154
161
 
@@ -158,23 +165,23 @@ async function executeRepo(context, args) {
158
165
  switch (command) {
159
166
  case "sync": {
160
167
  const { value: task, rest: remaining } = takeOption(rest, "--task");
161
- requireNoExtraArgs(remaining, "bun run rig repo sync [--task <beads-id>]");
168
+ requireNoExtraArgs(remaining, "rig repo sync [--task <task-id>]");
162
169
  withMutedConsole(context.outputMode === "json", () => repoEnsure(context.projectRoot, task || undefined));
163
170
  return { ok: true, group: "repo", command, details: { task: task || null } };
164
171
  }
165
172
  case "reset-baseline": {
166
173
  const { value: keepTaskStatusFlag, rest: remaining } = takeFlag(rest, "--keep-task-status");
167
- requireNoExtraArgs(remaining, "bun run rig repo reset-baseline [--keep-task-status]");
174
+ requireNoExtraArgs(remaining, "rig repo reset-baseline [--keep-task-status]");
168
175
  withMutedConsole(context.outputMode === "json", () => resetBaseline(context.projectRoot, keepTaskStatusFlag));
169
176
  return { ok: true, group: "repo", command, details: { keepTaskStatus: keepTaskStatusFlag } };
170
177
  }
171
178
  default:
172
- throw new CliError2(`Unknown repo command: ${command}`);
179
+ throw new CliError(`Unknown repo command: ${command}`, 1, { hint: "Run `rig repo --help` \u2014 commands are sync|reset-baseline." });
173
180
  }
174
181
  }
175
182
  async function executeGit(context, args) {
176
183
  if (args.length === 0) {
177
- throw new CliError2("Usage: bun run rig git <git-flow args...>");
184
+ throw new CliError("Usage: rig git <git-flow args...>");
178
185
  }
179
186
  await enforceNativeCommandPolicy(context, args, {
180
187
  commandPrefix: "rig-agent git",
@@ -187,15 +194,15 @@ async function executeGit(context, args) {
187
194
  return { ok: true, group: "git", command: args[0] ?? "git" };
188
195
  }
189
196
  try {
190
- await executeHarnessCommand(context.projectRoot, context.plugins, ["git", ...args]);
197
+ await executeHarnessCommand(context.projectRoot, ["git", ...args]);
191
198
  } catch (error) {
192
- throw new CliError2(error instanceof Error ? error.message : String(error), 2);
199
+ throw new CliError(error instanceof Error ? error.message : String(error), 2);
193
200
  }
194
201
  return { ok: true, group: "git", command: args[0] ?? "git" };
195
202
  }
196
203
  async function executeHarness(context, args) {
197
204
  if (args.length === 0) {
198
- throw new CliError2("Usage: bun run rig harness <harness args...>");
205
+ throw new CliError("Usage: rig harness <harness args...>");
199
206
  }
200
207
  await enforceNativeCommandPolicy(context, args, {
201
208
  commandPrefix: "rig-agent",
@@ -208,9 +215,9 @@ async function executeHarness(context, args) {
208
215
  return { ok: true, group: "harness", command: args[0] ?? "harness" };
209
216
  }
210
217
  try {
211
- await executeHarnessCommand(context.projectRoot, context.plugins, args);
218
+ await executeHarnessCommand(context.projectRoot, args);
212
219
  } catch (error) {
213
- throw new CliError2(error instanceof Error ? error.message : String(error), 2);
220
+ throw new CliError(error instanceof Error ? error.message : String(error), 2);
214
221
  }
215
222
  return { ok: true, group: "harness", command: args[0] ?? "harness" };
216
223
  }
@@ -0,0 +1,3 @@
1
+ import { type RunnerContext } from "../runner";
2
+ import type { CommandOutcome } from "@rig/runtime/control-plane/runtime/types";
3
+ export declare function executeRun(context: RunnerContext, args: string[]): Promise<CommandOutcome>;