@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
@@ -7,12 +7,19 @@ import { resolve as resolve4 } from "path";
7
7
 
8
8
  // packages/cli/src/runner.ts
9
9
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
10
- import { CliError } from "@rig/runtime/control-plane/errors";
10
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
11
11
  import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
12
- import { PluginManager } from "@rig/runtime/control-plane/runtime/plugins";
13
- import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/context";
14
12
  import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
15
- import { CliError as CliError2 } from "@rig/runtime/control-plane/errors";
13
+
14
+ class CliError extends RuntimeCliError {
15
+ hint;
16
+ constructor(message, exitCode = 1, options = {}) {
17
+ super(message, exitCode);
18
+ if (options.hint?.trim()) {
19
+ this.hint = options.hint.trim();
20
+ }
21
+ }
22
+ }
16
23
 
17
24
  // packages/cli/src/commands/_doctor-checks.ts
18
25
  import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
@@ -39,9 +46,14 @@ function readJsonFile(path) {
39
46
  try {
40
47
  return JSON.parse(readFileSync(path, "utf8"));
41
48
  } catch (error) {
42
- throw new CliError2(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1);
49
+ throw new CliError(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1, { hint: "Fix or delete that file, then re-select a server with `rig server use <alias|local>`." });
43
50
  }
44
51
  }
52
+ function writeJsonFile(path, value) {
53
+ mkdirSync(dirname(path), { recursive: true });
54
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
55
+ `, "utf8");
56
+ }
45
57
  function normalizeConnection(value) {
46
58
  if (!value || typeof value !== "object" || Array.isArray(value))
47
59
  return null;
@@ -82,29 +94,42 @@ function readRepoConnection(projectRoot) {
82
94
  return {
83
95
  selected,
84
96
  project: typeof record.project === "string" ? record.project : undefined,
85
- linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined
97
+ linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
98
+ serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
86
99
  };
87
100
  }
101
+ function writeRepoConnection(projectRoot, state) {
102
+ writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
103
+ }
88
104
  function resolveSelectedConnection(projectRoot, options = {}) {
89
105
  const repo = readRepoConnection(projectRoot);
90
106
  if (!repo)
91
107
  return null;
92
108
  if (repo.selected === "local")
93
- return { alias: "local", connection: { kind: "local", mode: "auto" } };
109
+ return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
94
110
  const global = readGlobalConnections(options);
95
111
  const connection = global.connections[repo.selected];
96
112
  if (!connection) {
97
- throw new CliError2(`Selected Rig connection "${repo.selected}" was not found. Run \`rig connect list\` or \`rig connect use local\`.`, 1);
113
+ throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
98
114
  }
99
- return { alias: repo.selected, connection };
115
+ return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
116
+ }
117
+ function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
118
+ const repo = readRepoConnection(projectRoot);
119
+ if (!repo)
120
+ return;
121
+ writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
100
122
  }
101
123
 
102
124
  // packages/cli/src/commands/_server-client.ts
103
- import { spawnSync } from "child_process";
104
125
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
105
126
  import { resolve as resolve2 } from "path";
106
127
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
107
- var cachedGitHubBearerToken;
128
+ var scopedGitHubBearerTokens = new Map;
129
+ var serverPhaseListener = null;
130
+ function reportServerPhase(label) {
131
+ serverPhaseListener?.(label);
132
+ }
108
133
  function cleanToken(value) {
109
134
  const trimmed = value?.trim();
110
135
  return trimmed ? trimmed : null;
@@ -121,49 +146,80 @@ function readPrivateRemoteSessionToken(projectRoot) {
121
146
  }
122
147
  }
123
148
  function readGitHubBearerTokenForRemote(projectRoot) {
124
- if (cachedGitHubBearerToken !== undefined)
125
- return cachedGitHubBearerToken;
149
+ const scopedKey = resolve2(projectRoot);
150
+ if (scopedGitHubBearerTokens.has(scopedKey))
151
+ return scopedGitHubBearerTokens.get(scopedKey) ?? null;
126
152
  const privateSession = readPrivateRemoteSessionToken(projectRoot);
127
- if (privateSession) {
128
- cachedGitHubBearerToken = privateSession;
129
- return cachedGitHubBearerToken;
130
- }
131
- const envToken = cleanToken(process.env.RIG_GITHUB_TOKEN) ?? cleanToken(process.env.GITHUB_TOKEN) ?? cleanToken(process.env.GH_TOKEN);
132
- if (envToken) {
133
- cachedGitHubBearerToken = envToken;
134
- return cachedGitHubBearerToken;
153
+ if (privateSession)
154
+ return privateSession;
155
+ return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
156
+ }
157
+ function readStoredGitHubAuthToken(projectRoot) {
158
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
159
+ if (!existsSync2(path))
160
+ return null;
161
+ try {
162
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
163
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
164
+ } catch {
165
+ return null;
135
166
  }
136
- const result = spawnSync("gh", ["auth", "token"], {
137
- encoding: "utf8",
138
- timeout: 5000,
139
- stdio: ["ignore", "pipe", "ignore"]
140
- });
141
- cachedGitHubBearerToken = result.status === 0 ? cleanToken(result.stdout) : null;
142
- return cachedGitHubBearerToken;
167
+ }
168
+ function readLocalConnectionFallbackToken(projectRoot) {
169
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
143
170
  }
144
171
  async function ensureServerForCli(projectRoot) {
145
172
  try {
146
173
  const selected = resolveSelectedConnection(projectRoot);
147
174
  if (selected?.connection.kind === "remote") {
175
+ reportServerPhase(`Connecting to ${selected.alias}\u2026`);
176
+ const authToken = readGitHubBearerTokenForRemote(projectRoot);
177
+ const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
148
178
  return {
149
179
  baseUrl: selected.connection.baseUrl,
150
- authToken: readGitHubBearerTokenForRemote(projectRoot),
151
- connectionKind: "remote"
180
+ authToken,
181
+ connectionKind: "remote",
182
+ serverProjectRoot
152
183
  };
153
184
  }
185
+ reportServerPhase("Starting local Rig server\u2026");
154
186
  const connection = await ensureLocalRigServerConnection(projectRoot);
155
187
  return {
156
188
  baseUrl: connection.baseUrl,
157
- authToken: connection.authToken,
158
- connectionKind: "local"
189
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
190
+ connectionKind: "local",
191
+ serverProjectRoot: resolve2(projectRoot)
159
192
  };
160
193
  } catch (error) {
161
194
  if (error instanceof Error) {
162
- throw new CliError2(error.message, 1);
195
+ throw new CliError(error.message, 1);
163
196
  }
164
197
  throw error;
165
198
  }
166
199
  }
200
+ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
201
+ const repo = readRepoConnection(projectRoot);
202
+ const slug = repo?.project?.trim();
203
+ if (!slug)
204
+ return null;
205
+ try {
206
+ const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
207
+ headers: mergeHeaders(undefined, authToken)
208
+ });
209
+ if (!response.ok)
210
+ return null;
211
+ const payload = await response.json();
212
+ const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
213
+ const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
214
+ const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
215
+ const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
216
+ if (path)
217
+ writeRepoServerProjectRoot(projectRoot, path);
218
+ return path;
219
+ } catch {
220
+ return null;
221
+ }
222
+ }
167
223
  function mergeHeaders(headers, authToken) {
168
224
  const merged = new Headers(headers);
169
225
  if (authToken) {
@@ -186,12 +242,65 @@ function diagnosticMessage(payload) {
186
242
  });
187
243
  return messages.length > 0 ? messages.join("; ") : null;
188
244
  }
245
+ var serverReachabilityCache = new Map;
246
+ async function probeServerReachability(baseUrl, authToken) {
247
+ try {
248
+ const response = await fetch(`${baseUrl.replace(/\/+$/, "")}/api/server/status`, {
249
+ headers: mergeHeaders(undefined, authToken),
250
+ signal: AbortSignal.timeout(1500)
251
+ });
252
+ return response.ok;
253
+ } catch {
254
+ return false;
255
+ }
256
+ }
257
+ function cachedServerReachability(projectRoot, baseUrl, authToken) {
258
+ const key = resolve2(projectRoot);
259
+ const cached = serverReachabilityCache.get(key);
260
+ if (cached)
261
+ return cached;
262
+ const probe = probeServerReachability(baseUrl, authToken);
263
+ serverReachabilityCache.set(key, probe);
264
+ return probe;
265
+ }
266
+ function describeSelectedServer(projectRoot, server) {
267
+ try {
268
+ const selected = resolveSelectedConnection(projectRoot);
269
+ if (selected) {
270
+ return {
271
+ alias: selected.alias,
272
+ target: selected.connection.kind === "remote" ? selected.connection.baseUrl : server.baseUrl
273
+ };
274
+ }
275
+ } catch {}
276
+ return { alias: server.connectionKind === "remote" ? "remote" : "local", target: server.baseUrl };
277
+ }
278
+ async function buildServerFailureContext(projectRoot, server) {
279
+ const { alias, target } = describeSelectedServer(projectRoot, server);
280
+ const reachable = await cachedServerReachability(projectRoot, server.baseUrl, server.authToken);
281
+ const reachability = reachable ? "server is reachable" : "server is unreachable";
282
+ return {
283
+ contextLine: `Currently connected to: ${alias} at ${target} (${reachability}).`,
284
+ hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
285
+ };
286
+ }
189
287
  async function requestServerJson(context, pathname, init = {}) {
190
288
  const server = await ensureServerForCli(context.projectRoot);
191
- const response = await fetch(`${server.baseUrl}${pathname}`, {
192
- ...init,
193
- headers: mergeHeaders(init.headers, server.authToken)
194
- });
289
+ const headers = mergeHeaders(init.headers, server.authToken);
290
+ if (server.serverProjectRoot)
291
+ headers.set("x-rig-project-root", server.serverProjectRoot);
292
+ reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
293
+ let response;
294
+ try {
295
+ response = await fetch(`${server.baseUrl}${pathname}`, {
296
+ ...init,
297
+ headers
298
+ });
299
+ } catch (error) {
300
+ const failure = await buildServerFailureContext(context.projectRoot, server);
301
+ throw new CliError(`Rig server request failed: ${error instanceof Error ? error.message : String(error)}
302
+ ${failure.contextLine}`, 1, { hint: failure.hint });
303
+ }
195
304
  const text = await response.text();
196
305
  const payload = text.trim().length > 0 ? (() => {
197
306
  try {
@@ -202,11 +311,26 @@ async function requestServerJson(context, pathname, init = {}) {
202
311
  })() : null;
203
312
  if (!response.ok) {
204
313
  const diagnostics = diagnosticMessage(payload);
205
- const detail = diagnostics ?? (text || response.statusText);
206
- throw new CliError2(`Rig server request failed (${response.status}): ${detail}`, 1);
314
+ const rawDetail = diagnostics ?? (text || response.statusText);
315
+ const detail = diagnostics ? rawDetail : rawDetail.split(`
316
+ `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
317
+ const failure = await buildServerFailureContext(context.projectRoot, server);
318
+ throw new CliError(`Rig server request failed (${response.status}): ${detail}
319
+ ${failure.contextLine}`, 1, { hint: failure.hint });
207
320
  }
208
321
  return payload;
209
322
  }
323
+ var RESUMABLE_RUN_STATUSES = new Set([
324
+ "created",
325
+ "preparing",
326
+ "running",
327
+ "validating",
328
+ "reviewing",
329
+ "stopped",
330
+ "failed",
331
+ "needs-attention",
332
+ "needs_attention"
333
+ ]);
210
334
 
211
335
  // packages/cli/src/commands/_parsers.ts
212
336
  async function loadRigConfigOrNull(projectRoot) {
@@ -222,7 +346,8 @@ async function loadRigConfigOrNull(projectRoot) {
222
346
  import { existsSync as existsSync3, readFileSync as readFileSync3, rmSync } from "fs";
223
347
  import { homedir as homedir2 } from "os";
224
348
  import { resolve as resolve3 } from "path";
225
- var PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
349
+ var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
350
+ var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
226
351
  async function defaultCommandRunner(command, options = {}) {
227
352
  const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
228
353
  const [stdout, stderr, exitCode] = await Promise.all([
@@ -241,7 +366,7 @@ function resolvePiHomeDir(inputHomeDir) {
241
366
  function piListContainsPiRig(output) {
242
367
  return output.split(/\r?\n/).some((line) => {
243
368
  const normalized = line.trim();
244
- return normalized.includes(PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
369
+ return normalized.includes(PI_RIG_PACKAGE_NAME) || normalized.includes(LEGACY_PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
245
370
  });
246
371
  }
247
372
  async function safeRun(runner, command, options) {
@@ -409,7 +534,10 @@ async function runRigDoctorChecks(options) {
409
534
  const bunVersion = options.bunVersion ?? Bun.version;
410
535
  const request = options.requestJson ?? ((pathname, init) => requestServerJson({ projectRoot }, pathname, init));
411
536
  const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
537
+ const progress = options.onProgress ?? (() => {});
538
+ progress("Checking local toolchain\u2026");
412
539
  checks.push(check("bun", `bun >= ${MIN_SUPPORTED_BUN_VERSION}`, isSupportedBunVersion(bunVersion) ? "pass" : "fail", `found ${bunVersion}`, `Install Bun ${MIN_SUPPORTED_BUN_VERSION} or newer.`), check("git", "git", which("git") ? "pass" : "fail", which("git") ?? undefined, "Install git and ensure it is on PATH."), check("jq", "jq", which("jq") ? "pass" : "warn", which("jq") ?? undefined, "Install jq (for example `brew install jq`)."));
540
+ progress("Loading rig.config\u2026");
413
541
  const loadedConfig = await loadConfig(projectRoot).catch(() => null);
414
542
  const config = loadedConfig ?? loadFallbackConfig(projectRoot);
415
543
  const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync4(resolve4(projectRoot, name)));
@@ -417,7 +545,7 @@ async function runRigDoctorChecks(options) {
417
545
  const taskSourceKind = config?.taskSource?.kind;
418
546
  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."));
419
547
  const repo = readRepoConnection(projectRoot);
420
- checks.push(repo ? check("project-link", "repo selected Rig connection", 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 connection", "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig connect use <alias|local>`."));
548
+ 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>`."));
421
549
  const selected = (() => {
422
550
  try {
423
551
  return resolveSelectedConnection(projectRoot);
@@ -425,9 +553,10 @@ async function runRigDoctorChecks(options) {
425
553
  return null;
426
554
  }
427
555
  })();
428
- checks.push(selected ? check("connection", "selected server connection", "pass", selected.connection.kind === "remote" ? selected.connection.baseUrl : "local auto") : check("connection", "selected server connection", repo ? "fail" : "warn", repo ? "selected alias is missing" : "will auto-start local server", repo ? "Run `rig connect list` and `rig connect use <alias|local>`." : undefined));
556
+ 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));
429
557
  let server = null;
430
558
  try {
559
+ progress("Connecting to the selected Rig server\u2026");
431
560
  server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
432
561
  checks.push(check("server", "Rig server reachable", "pass", `${server.connectionKind} ${server.baseUrl}`));
433
562
  } catch (error) {
@@ -435,18 +564,21 @@ async function runRigDoctorChecks(options) {
435
564
  }
436
565
  if (server || options.requestJson) {
437
566
  try {
567
+ progress("Checking server status\u2026");
438
568
  const status = await request("/api/server/status");
439
569
  checks.push(check("server-status", "server project status", "pass", JSON.stringify(status).slice(0, 180)));
440
570
  } catch (error) {
441
571
  checks.push(check("server-status", "server project status", "fail", errorMessage(error), "Run `rig doctor` after the selected server is reachable."));
442
572
  }
443
573
  try {
574
+ progress("Checking GitHub auth\u2026");
444
575
  const auth = await request("/api/github/auth/status");
445
576
  checks.push(isAuthenticated(auth) ? check("github-auth", "GitHub auth", "pass") : check("github-auth", "GitHub auth", "fail", "not authenticated", "Run `rig github auth import-gh` or `rig github auth token --token <token>`."));
446
577
  } catch (error) {
447
578
  checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
448
579
  }
449
580
  try {
581
+ progress("Checking GitHub repo permissions\u2026");
450
582
  const permissions = await request("/api/github/repo/permissions");
451
583
  const allowed = permissionAllowsPr(permissions);
452
584
  checks.push(allowed === true ? check("github-repo-permissions", "GitHub repo PR permissions", "pass", JSON.stringify(permissions).slice(0, 180)) : allowed === false ? check("github-repo-permissions", "GitHub repo PR permissions", "fail", JSON.stringify(permissions).slice(0, 180), "Grant the selected GitHub token permission to push branches, open PRs, and merge according to repo rules.") : check("github-repo-permissions", "GitHub repo PR permissions", "warn", JSON.stringify(permissions).slice(0, 180), "Confirm the selected token can push branches and open PRs."));
@@ -454,6 +586,7 @@ async function runRigDoctorChecks(options) {
454
586
  checks.push(check("github-repo-permissions", "GitHub repo PR permissions", "warn", errorMessage(error), "Ensure the server exposes repo permission checks and the token can open PRs."));
455
587
  }
456
588
  try {
589
+ progress("Checking GitHub issue labels\u2026");
457
590
  const labels = await request("/api/workspace/task-labels");
458
591
  const ready = labelsReady(labels);
459
592
  checks.push(ready === false ? check("task-labels", "GitHub issue labels", "fail", JSON.stringify(labels).slice(0, 180), "Let Rig create required labels or create the configured lifecycle labels manually.") : check("task-labels", "GitHub issue labels", ready === true ? "pass" : "warn", JSON.stringify(labels).slice(0, 180), "Confirm required Rig lifecycle labels exist."));
@@ -461,6 +594,7 @@ async function runRigDoctorChecks(options) {
461
594
  checks.push(check("task-labels", "GitHub issue labels", "warn", errorMessage(error), "Run `rig init`/`rig doctor` after label setup is wired on the server."));
462
595
  }
463
596
  try {
597
+ progress("Checking task projection\u2026");
464
598
  const projection = await request("/api/workspace/task-projection");
465
599
  checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
466
600
  } catch (error) {
@@ -469,6 +603,7 @@ async function runRigDoctorChecks(options) {
469
603
  const slug = projectStatusSlug(projectRoot, config);
470
604
  if (slug) {
471
605
  try {
606
+ progress("Checking server project checkout\u2026");
472
607
  const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
473
608
  checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
474
609
  } catch (error) {
@@ -483,6 +618,7 @@ async function runRigDoctorChecks(options) {
483
618
  }
484
619
  checks.push(githubProjectsCheck(config));
485
620
  checks.push(prMergeCheck(config));
621
+ progress("Checking Pi installation\u2026");
486
622
  const piChecks = await (options.piChecks ?? (() => buildPiSetupChecks()))().catch((error) => [{
487
623
  ok: false,
488
624
  label: "pi/pi-rig checks",
@@ -508,7 +644,7 @@ function countDoctorFailures(checks) {
508
644
  function throwIfDoctorFailed(checks) {
509
645
  const failures = countDoctorFailures(checks);
510
646
  if (failures > 0) {
511
- throw new CliError2(`Doctor failed (${failures} failing check${failures === 1 ? "" : "s"}).`, 1);
647
+ throw new CliError(`Doctor failed (${failures} failing check${failures === 1 ? "" : "s"}).`, 1);
512
648
  }
513
649
  }
514
650
  export {
@@ -0,0 +1,51 @@
1
+ export type HelpCommand = {
2
+ command: string;
3
+ description: string;
4
+ primary?: boolean;
5
+ };
6
+ export type HelpGroup = {
7
+ name: string;
8
+ summary: string;
9
+ usage: string[];
10
+ commands: HelpCommand[];
11
+ examples?: string[];
12
+ next?: string[];
13
+ advanced?: string[];
14
+ };
15
+ export type TopLevelSection = {
16
+ title: string;
17
+ subtitle: string;
18
+ commands: HelpCommand[];
19
+ };
20
+ /** Catalog DATA for the app's help view — the view builds its own layout
21
+ * from these; the render* functions below remain for plain/script output. */
22
+ export declare function helpCatalog(): {
23
+ sections: readonly TopLevelSection[];
24
+ groups: readonly HelpGroup[];
25
+ };
26
+ /**
27
+ * Night City boot screen. Rendered only on interactive TTY launches — plain
28
+ * mode and --json never see it.
29
+ */
30
+ export declare function renderRigBanner(version?: string): string;
31
+ export declare function renderTopLevelHelp(): string;
32
+ export declare function renderAdvancedHelp(): string;
33
+ export declare function renderGroupHelp(groupName: string): string | null;
34
+ export declare function listHelpGroups(): string[];
35
+ /**
36
+ * Fuzzy-match a bare word against known group subcommand names so the
37
+ * unknown-command error can suggest the canonical `rig <group> <cmd>`
38
+ * spelling. Primary groups win ties (ALL_GROUPS is primary-first).
39
+ */
40
+ export declare function suggestGroupCommandForWord(word: string): string | null;
41
+ export type TopLevelLaunchState = {
42
+ /** True when the cwd resolves to an initialized Rig project. */
43
+ projectInitialized?: boolean;
44
+ /** Short description of the selected server connection, if known. */
45
+ selectedServer?: string | null;
46
+ /** CLI version for the banner footer. */
47
+ version?: string;
48
+ };
49
+ export declare function printTopLevelHelp(state?: TopLevelLaunchState): void;
50
+ export declare function printAdvancedHelp(): void;
51
+ export declare function printGroupHelpDocument(groupName: string): void;