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

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 (118) hide show
  1. package/README.md +18 -19
  2. package/dist/bin/build-rig-binaries.js +22 -10
  3. package/dist/bin/rig.d.ts +71 -1
  4. package/dist/bin/rig.js +15078 -11169
  5. package/dist/config/rig-default-config.yml +5 -0
  6. package/dist/src/app/drone-ui.d.ts +11 -14
  7. package/dist/src/app/drone-ui.js +70 -86
  8. package/dist/src/commands/_async-ui.d.ts +1 -4
  9. package/dist/src/commands/_async-ui.js +9 -111
  10. package/dist/src/commands/_cli-format.d.ts +16 -9
  11. package/dist/src/commands/_cli-format.js +167 -295
  12. package/dist/src/commands/_connection-state.d.ts +11 -1
  13. package/dist/src/commands/_connection-state.js +50 -5
  14. package/dist/src/commands/_doctor-checks.d.ts +0 -6
  15. package/dist/src/commands/_doctor-checks.js +79 -382
  16. package/dist/src/commands/_help-catalog.d.ts +1 -1
  17. package/dist/src/commands/_help-catalog.js +217 -157
  18. package/dist/src/commands/_inprocess-services.d.ts +33 -0
  19. package/dist/src/commands/_inprocess-services.js +102 -0
  20. package/dist/src/commands/_json-output.js +4 -0
  21. package/dist/src/commands/_lazy-reconcile.d.ts +34 -0
  22. package/dist/src/commands/_lazy-reconcile.js +102 -0
  23. package/dist/src/commands/_paths.js +1 -1
  24. package/dist/src/commands/_pi-frontend.d.ts +18 -10
  25. package/dist/src/commands/_pi-frontend.js +37 -715
  26. package/dist/src/commands/_pi-install.js +18 -36
  27. package/dist/src/commands/_policy.d.ts +1 -1
  28. package/dist/src/commands/_policy.js +56 -15
  29. package/dist/src/commands/_run-bridge.d.ts +114 -0
  30. package/dist/src/commands/_run-bridge.js +387 -0
  31. package/dist/src/commands/_run-diagnostics.d.ts +9 -0
  32. package/dist/src/commands/_run-diagnostics.js +51 -0
  33. package/dist/src/commands/_run-driver-helpers.d.ts +8 -81
  34. package/dist/src/commands/_run-driver-helpers.js +79 -283
  35. package/dist/src/commands/_run-projection.d.ts +50 -0
  36. package/dist/src/commands/_run-projection.js +349 -0
  37. package/dist/src/commands/_run-subcommands.d.ts +3 -0
  38. package/dist/src/commands/_run-subcommands.js +31 -0
  39. package/dist/src/commands/_spinner.js +1 -1
  40. package/dist/src/commands/agent.d.ts +1 -1
  41. package/dist/src/commands/agent.js +8559 -239
  42. package/dist/src/commands/dist.d.ts +1 -1
  43. package/dist/src/commands/dist.js +27 -19
  44. package/dist/src/commands/doctor.d.ts +1 -1
  45. package/dist/src/commands/doctor.js +93 -475
  46. package/dist/src/commands/github.d.ts +1 -1
  47. package/dist/src/commands/github.js +113 -387
  48. package/dist/src/commands/inbox.d.ts +22 -24
  49. package/dist/src/commands/inbox.js +420 -691
  50. package/dist/src/commands/init.d.ts +6 -16
  51. package/dist/src/commands/init.js +334 -971
  52. package/dist/src/commands/inspect.d.ts +19 -2
  53. package/dist/src/commands/inspect.js +644 -610
  54. package/dist/src/commands/pi.d.ts +1 -1
  55. package/dist/src/commands/plugin.d.ts +1 -1
  56. package/dist/src/commands/plugin.js +486 -7
  57. package/dist/src/commands/profile-and-review.d.ts +1 -1
  58. package/dist/src/commands/profile-and-review.js +94 -56
  59. package/dist/src/commands/queue.js +1 -21
  60. package/dist/src/commands/remote.d.ts +1 -1
  61. package/dist/src/commands/remote.js +837 -14
  62. package/dist/src/commands/repo-git-harness.d.ts +1 -1
  63. package/dist/src/commands/repo-git-harness.js +57 -14
  64. package/dist/src/commands/run.d.ts +20 -2
  65. package/dist/src/commands/run.js +17579 -1759
  66. package/dist/src/commands/server.d.ts +2 -6
  67. package/dist/src/commands/server.js +141 -723
  68. package/dist/src/commands/setup.d.ts +1 -1
  69. package/dist/src/commands/setup.js +102 -484
  70. package/dist/src/commands/stats.d.ts +13 -10
  71. package/dist/src/commands/stats.js +689 -761
  72. package/dist/src/commands/task-run-driver.d.ts +50 -88
  73. package/dist/src/commands/task-run-driver.js +116 -2717
  74. package/dist/src/commands/task.d.ts +34 -13
  75. package/dist/src/commands/task.js +668 -2523
  76. package/dist/src/commands/test.d.ts +1 -1
  77. package/dist/src/commands/triage.d.ts +11 -0
  78. package/dist/src/commands/triage.js +227 -0
  79. package/dist/src/commands/workspace.d.ts +1 -1
  80. package/dist/src/commands.d.ts +0 -16
  81. package/dist/src/commands.js +16657 -12250
  82. package/dist/src/index.js +16528 -12497
  83. package/dist/src/launcher.js +4 -0
  84. package/dist/src/operator-cli.d.ts +2 -0
  85. package/dist/src/operator-cli.js +17837 -0
  86. package/dist/src/operator-entry.d.ts +1 -0
  87. package/dist/src/operator-entry.js +3 -0
  88. package/package.json +18 -12
  89. package/dist/src/app/board.d.ts +0 -23
  90. package/dist/src/app/board.js +0 -1786
  91. package/dist/src/app/theme.d.ts +0 -47
  92. package/dist/src/app/theme.js +0 -150
  93. package/dist/src/commands/_authority-runs.d.ts +0 -22
  94. package/dist/src/commands/_authority-runs.js +0 -110
  95. package/dist/src/commands/_operator-surface.d.ts +0 -34
  96. package/dist/src/commands/_operator-surface.js +0 -220
  97. package/dist/src/commands/_operator-view.d.ts +0 -30
  98. package/dist/src/commands/_operator-view.js +0 -1070
  99. package/dist/src/commands/_preflight.d.ts +0 -22
  100. package/dist/src/commands/_preflight.js +0 -540
  101. package/dist/src/commands/_run-replay.d.ts +0 -24
  102. package/dist/src/commands/_run-replay.js +0 -142
  103. package/dist/src/commands/_server-client.d.ts +0 -186
  104. package/dist/src/commands/_server-client.js +0 -681
  105. package/dist/src/commands/_snapshot-upload.d.ts +0 -39
  106. package/dist/src/commands/_snapshot-upload.js +0 -455
  107. package/dist/src/commands/_task-picker.d.ts +0 -9
  108. package/dist/src/commands/_task-picker.js +0 -201
  109. package/dist/src/commands/browser.d.ts +0 -65
  110. package/dist/src/commands/browser.js +0 -1173
  111. package/dist/src/commands/connect.d.ts +0 -7
  112. package/dist/src/commands/connect.js +0 -419
  113. package/dist/src/commands/inspector.d.ts +0 -3
  114. package/dist/src/commands/inspector.js +0 -263
  115. package/dist/src/commands/task-report-bug.d.ts +0 -19
  116. package/dist/src/commands/task-report-bug.js +0 -1281
  117. package/dist/src/report-bug.d.ts +0 -44
  118. package/dist/src/report-bug.js +0 -260
@@ -2,8 +2,8 @@
2
2
  var __require = import.meta.require;
3
3
 
4
4
  // packages/cli/src/commands/setup.ts
5
- import { existsSync as existsSync5, mkdirSync as mkdirSync2, readdirSync, writeFileSync as writeFileSync2 } from "fs";
6
- import { resolve as resolve6 } from "path";
5
+ import { existsSync as existsSync4, mkdirSync as mkdirSync2, readdirSync, writeFileSync as writeFileSync2 } from "fs";
6
+ import { resolve as resolve5 } from "path";
7
7
 
8
8
  // packages/cli/src/runner.ts
9
9
  import { EventBus } from "@rig/runtime/control-plane/runtime/events";
@@ -85,7 +85,7 @@ async function loadRigConfigOrNull(projectRoot) {
85
85
 
86
86
  // packages/cli/src/commands/_paths.ts
87
87
  import { resolve } from "path";
88
- import { resolveMonorepoRoot } from "@rig/runtime/control-plane/native/utils";
88
+ import { resolveMonorepoRoot } from "@rig/runtime/layout";
89
89
  function resolveControlPlaneMonorepoRoot(projectRoot) {
90
90
  return resolveMonorepoRoot(projectRoot);
91
91
  }
@@ -106,11 +106,10 @@ function resolveControlPlaneDefinitionRoot(projectRoot) {
106
106
  }
107
107
 
108
108
  // packages/cli/src/commands/_pi-install.ts
109
- import { existsSync, readFileSync, rmSync } from "fs";
109
+ import { existsSync } from "fs";
110
110
  import { homedir } from "os";
111
111
  import { resolve as resolve2 } from "path";
112
112
  var PI_RIG_PACKAGE_NAME = "@h-rig/pi-rig";
113
- var LEGACY_PI_RIG_PACKAGE_NAME = "@rig/pi-rig";
114
113
  async function defaultCommandRunner(command, options = {}) {
115
114
  const proc = Bun.spawn(command, { cwd: options.cwd, stdout: "pipe", stderr: "pipe" });
116
115
  const [stdout, stderr, exitCode] = await Promise.all([
@@ -129,7 +128,7 @@ function resolvePiHomeDir(inputHomeDir) {
129
128
  function piListContainsPiRig(output) {
130
129
  return output.split(/\r?\n/).some((line) => {
131
130
  const normalized = line.trim();
132
- return normalized.includes(PI_RIG_PACKAGE_NAME) || normalized.includes(LEGACY_PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
131
+ return normalized.includes(PI_RIG_PACKAGE_NAME) || /(?:^|[\\/])packages[\\/]pi-rig(?:$|\s)/.test(normalized);
133
132
  });
134
133
  }
135
134
  async function safeRun(runner, command, options) {
@@ -149,27 +148,25 @@ async function checkPiRigInstall(input = {}) {
149
148
  piRig: { ok: true, label: "pi-rig global extension", detail: extensionPath }
150
149
  };
151
150
  }
152
- const exists = input.exists ?? existsSync;
153
151
  const runner = input.commandRunner ?? defaultCommandRunner;
154
152
  const piResult = await safeRun(runner, ["pi", "--version"]);
155
153
  const piListResult = piResult.exitCode === 0 ? await safeRun(runner, ["pi", "list"]) : { exitCode: 1, stdout: "", stderr: "" };
156
- const listedPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
154
+ const hasPiRig = piListResult.exitCode === 0 && piListContainsPiRig(`${piListResult.stdout}
157
155
  ${piListResult.stderr}`);
158
- const legacyBridge = exists(resolve2(extensionPath, "index.ts"));
159
- const hasPiRig = listedPiRig;
156
+ const hasLegacyBridgeScaffold = !hasPiRig && (input.exists ?? existsSync)(extensionPath);
160
157
  return {
161
158
  extensionPath,
162
159
  pi: {
163
160
  ok: piResult.exitCode === 0,
164
161
  label: "pi",
165
162
  detail: (piResult.stdout || piResult.stderr).trim() || undefined,
166
- hint: piResult.exitCode === 0 ? undefined : "Install Pi or run `rig init --yes` to install/update the Pi runtime."
163
+ hint: piResult.exitCode === 0 ? undefined : "Install Pi/OMP manually or set RIG_PI_INSTALL_COMMAND before verifying with bare `rig` / Cockpit \u2192 Doctor."
167
164
  },
168
165
  piRig: {
169
166
  ok: hasPiRig,
170
167
  label: "pi-rig global extension",
171
- detail: hasPiRig ? piListResult.stdout.trim() || PI_RIG_PACKAGE_NAME : legacyBridge ? `${extensionPath} (legacy bridge; reinstall required)` : undefined,
172
- hint: hasPiRig ? undefined : "Run `rig init --yes` to install/enable the global pi-rig package with `pi install`."
168
+ detail: hasPiRig ? piListResult.stdout.trim() || PI_RIG_PACKAGE_NAME : hasLegacyBridgeScaffold ? `legacy bridge scaffold at ${extensionPath}` : undefined,
169
+ hint: hasPiRig ? undefined : `Install the Rig OMP extension with \`pi install ${PI_RIG_PACKAGE_NAME}\`, then verify with bare \`rig\` / Cockpit \u2192 Doctor.`
173
170
  }
174
171
  };
175
172
  }
@@ -179,23 +176,13 @@ async function buildPiSetupChecks(input = {}) {
179
176
  }
180
177
 
181
178
  // packages/cli/src/commands/_doctor-checks.ts
182
- import { existsSync as existsSync4, readFileSync as readFileSync4 } from "fs";
183
- import { resolve as resolve5 } from "path";
179
+ import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
180
+ import { resolve as resolve4 } from "path";
184
181
  import { isSupportedBunVersion, MIN_SUPPORTED_BUN_VERSION } from "@rig/runtime/control-plane/setup-version";
185
182
 
186
183
  // packages/cli/src/commands/_connection-state.ts
187
- import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "fs";
188
- import { homedir as homedir2 } from "os";
184
+ import { existsSync as existsSync2, mkdirSync, readFileSync, writeFileSync } from "fs";
189
185
  import { dirname, resolve as resolve3 } from "path";
190
- function resolveGlobalConnectionsPath(env = process.env) {
191
- const explicit = env.RIG_CONNECTIONS_FILE?.trim();
192
- if (explicit)
193
- return resolve3(explicit);
194
- const stateDir = env.RIG_GLOBAL_STATE_DIR?.trim();
195
- if (stateDir)
196
- return resolve3(stateDir, "connections.json");
197
- return resolve3(homedir2(), ".rig", "connections.json");
198
- }
199
186
  function resolveRepoConnectionPath(projectRoot) {
200
187
  return resolve3(projectRoot, ".rig", "state", "connection.json");
201
188
  }
@@ -203,45 +190,11 @@ function readJsonFile(path) {
203
190
  if (!existsSync2(path))
204
191
  return null;
205
192
  try {
206
- return JSON.parse(readFileSync2(path, "utf8"));
193
+ return JSON.parse(readFileSync(path, "utf8"));
207
194
  } catch (error) {
208
195
  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>`." });
209
196
  }
210
197
  }
211
- function writeJsonFile(path, value) {
212
- mkdirSync(dirname(path), { recursive: true });
213
- writeFileSync(path, `${JSON.stringify(value, null, 2)}
214
- `, "utf8");
215
- }
216
- function normalizeConnection(value) {
217
- if (!value || typeof value !== "object" || Array.isArray(value))
218
- return null;
219
- const record = value;
220
- if (record.kind === "local")
221
- return { kind: "local", mode: "auto" };
222
- if (record.kind === "remote" && typeof record.baseUrl === "string" && record.baseUrl.trim()) {
223
- const baseUrl = record.baseUrl.trim().replace(/\/+$/, "");
224
- return { kind: "remote", baseUrl };
225
- }
226
- return null;
227
- }
228
- function readGlobalConnections(options = {}) {
229
- const path = resolveGlobalConnectionsPath(options.env ?? process.env);
230
- const payload = readJsonFile(path);
231
- if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
232
- return { connections: {} };
233
- }
234
- const rawConnections = payload.connections;
235
- const connections = {};
236
- if (rawConnections && typeof rawConnections === "object" && !Array.isArray(rawConnections)) {
237
- for (const [alias, raw] of Object.entries(rawConnections)) {
238
- const connection = normalizeConnection(raw);
239
- if (connection)
240
- connections[alias] = connection;
241
- }
242
- }
243
- return { connections };
244
- }
245
198
  function readRepoConnection(projectRoot) {
246
199
  const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
247
200
  if (!payload || typeof payload !== "object" || Array.isArray(payload))
@@ -254,247 +207,68 @@ function readRepoConnection(projectRoot) {
254
207
  selected,
255
208
  project: typeof record.project === "string" ? record.project : undefined,
256
209
  linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
257
- serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
210
+ serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined,
211
+ serverProjectRootAlias: typeof record.serverProjectRootAlias === "string" && record.serverProjectRootAlias.trim() ? record.serverProjectRootAlias.trim() : undefined,
212
+ serverProjectRootBaseUrl: typeof record.serverProjectRootBaseUrl === "string" && record.serverProjectRootBaseUrl.trim() ? record.serverProjectRootBaseUrl.trim().replace(/\/+$/, "") : undefined
258
213
  };
259
214
  }
260
- function writeRepoConnection(projectRoot, state) {
261
- writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
262
- }
263
- function resolveSelectedConnection(projectRoot, options = {}) {
264
- const repo = readRepoConnection(projectRoot);
265
- if (!repo)
266
- return null;
267
- if (repo.selected === "local")
268
- return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
269
- const global = readGlobalConnections(options);
270
- const connection = global.connections[repo.selected];
271
- if (!connection) {
272
- throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
273
- }
274
- return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
275
- }
276
- function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
277
- const repo = readRepoConnection(projectRoot);
278
- if (!repo)
279
- return;
280
- writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
281
- }
282
215
 
283
- // packages/cli/src/commands/_server-client.ts
284
- import { existsSync as existsSync3, readFileSync as readFileSync3 } from "fs";
285
- import { resolve as resolve4 } from "path";
286
- import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
216
+ // packages/cli/src/commands/_inprocess-services.ts
217
+ import {
218
+ beginGitHubDeviceFlow,
219
+ checkGitHubRepoPermissions,
220
+ createGitHubAuthStore,
221
+ listGitHubProjects,
222
+ pollGitHubDeviceFlow,
223
+ resolveGitHubAuthStatus,
224
+ resolveProjectStatusField,
225
+ saveGitHubTokenForProject
226
+ } from "@rig/runtime/control-plane/github/index";
287
227
  var scopedGitHubBearerTokens = new Map;
288
- var serverPhaseListener = null;
289
- function setServerPhaseListener(listener) {
290
- const previous = serverPhaseListener;
291
- serverPhaseListener = listener;
292
- return previous;
293
- }
294
- function reportServerPhase(label) {
295
- serverPhaseListener?.(label);
296
- }
297
228
  function cleanToken(value) {
298
229
  const trimmed = value?.trim();
299
230
  return trimmed ? trimmed : null;
300
231
  }
301
- function readPrivateRemoteSessionToken(projectRoot) {
302
- const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
303
- if (!existsSync3(path))
304
- return null;
305
- try {
306
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
307
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
308
- } catch {
309
- return null;
310
- }
311
- }
312
- function readGitHubBearerTokenForRemote(projectRoot) {
313
- const scopedKey = resolve4(projectRoot);
314
- if (scopedGitHubBearerTokens.has(scopedKey))
315
- return scopedGitHubBearerTokens.get(scopedKey) ?? null;
316
- const privateSession = readPrivateRemoteSessionToken(projectRoot);
317
- if (privateSession)
318
- return privateSession;
319
- return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
320
- }
321
- function readStoredGitHubAuthToken(projectRoot) {
322
- const path = resolve4(projectRoot, ".rig", "state", "github-auth.json");
323
- if (!existsSync3(path))
324
- return null;
325
- try {
326
- const parsed = JSON.parse(readFileSync3(path, "utf8"));
327
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
328
- } catch {
329
- return null;
330
- }
331
- }
332
- function readLocalConnectionFallbackToken(projectRoot) {
333
- return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
334
- }
335
- async function ensureServerForCli(projectRoot) {
336
- try {
337
- const selected = resolveSelectedConnection(projectRoot);
338
- if (selected?.connection.kind === "remote") {
339
- reportServerPhase(`Connecting to ${selected.alias}\u2026`);
340
- const authToken = readGitHubBearerTokenForRemote(projectRoot);
341
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
342
- return {
343
- baseUrl: selected.connection.baseUrl,
344
- authToken,
345
- connectionKind: "remote",
346
- serverProjectRoot
347
- };
348
- }
349
- reportServerPhase("Starting local Rig server\u2026");
350
- const connection = await ensureLocalRigServerConnection(projectRoot);
351
- return {
352
- baseUrl: connection.baseUrl,
353
- authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
354
- connectionKind: "local",
355
- serverProjectRoot: resolve4(projectRoot)
356
- };
357
- } catch (error) {
358
- if (error instanceof Error) {
359
- throw new CliError(error.message, 1);
360
- }
361
- throw error;
362
- }
363
- }
364
- async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
365
- const repo = readRepoConnection(projectRoot);
366
- const slug = repo?.project?.trim();
367
- if (!slug)
368
- return null;
369
- try {
370
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
371
- headers: mergeHeaders(undefined, authToken)
232
+ function cleanString(value) {
233
+ return typeof value === "string" && value.trim() ? value.trim() : null;
234
+ }
235
+ function oauthClientId() {
236
+ return cleanToken(process.env.RIG_GITHUB_OAUTH_CLIENT_ID);
237
+ }
238
+ async function getGitHubAuthStatusInProcess(context) {
239
+ return { ok: true, ...resolveGitHubAuthStatus({ projectRoot: context.projectRoot, oauthConfigured: Boolean(oauthClientId()) }) };
240
+ }
241
+ async function requestGitHubAuthJsonInProcess(context, pathname, init = {}) {
242
+ const method = (init.method ?? "GET").toUpperCase();
243
+ if (pathname === "/api/github/auth/status")
244
+ return getGitHubAuthStatusInProcess(context);
245
+ if (pathname === "/api/github/repo/permissions") {
246
+ return checkGitHubRepoPermissions({ projectRoot: context.projectRoot, oauthConfigured: Boolean(oauthClientId()) });
247
+ }
248
+ if (pathname === "/api/github/auth/device/start" && method === "POST") {
249
+ const clientId = oauthClientId();
250
+ if (!clientId)
251
+ return { ok: false, oauthConfigured: false, error: "RIG_GITHUB_OAUTH_CLIENT_ID is not configured." };
252
+ const body = init.body ? JSON.parse(String(init.body)) : {};
253
+ return beginGitHubDeviceFlow({
254
+ projectRoot: context.projectRoot,
255
+ clientId,
256
+ scope: cleanString(body.scope) ?? undefined,
257
+ selectedRepo: cleanString(body.repoSlug)
372
258
  });
373
- if (!response.ok)
374
- return null;
375
- const payload = await response.json();
376
- const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
377
- const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
378
- const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
379
- const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
380
- if (path)
381
- writeRepoServerProjectRoot(projectRoot, path);
382
- return path;
383
- } catch {
384
- return null;
385
259
  }
386
- }
387
- function mergeHeaders(headers, authToken) {
388
- const merged = new Headers(headers);
389
- if (authToken) {
390
- merged.set("authorization", `Bearer ${authToken}`);
260
+ if (pathname === "/api/github/auth/device/poll" && method === "POST") {
261
+ const clientId = oauthClientId();
262
+ if (!clientId)
263
+ return { ok: false, oauthConfigured: false, error: "RIG_GITHUB_OAUTH_CLIENT_ID is not configured." };
264
+ const body = init.body ? JSON.parse(String(init.body)) : {};
265
+ const pollId = cleanString(body.pollId);
266
+ if (!pollId)
267
+ return { ok: false, status: "error", error: "pollId is required" };
268
+ return pollGitHubDeviceFlow({ projectRoot: context.projectRoot, clientId, pollId, selectedRepo: cleanString(body.repoSlug) });
391
269
  }
392
- return merged;
270
+ throw new Error(`No in-process GitHub auth API for ${method} ${pathname}`);
393
271
  }
394
- function diagnosticMessage(payload) {
395
- if (!payload || typeof payload !== "object" || Array.isArray(payload))
396
- return null;
397
- const record = payload;
398
- const diagnostics = Array.isArray(record.diagnostics) ? record.diagnostics : [];
399
- const messages = diagnostics.flatMap((entry) => {
400
- if (!entry || typeof entry !== "object" || Array.isArray(entry))
401
- return [];
402
- const diagnostic = entry;
403
- const kind = typeof diagnostic.kind === "string" ? diagnostic.kind : "task-source";
404
- const message = typeof diagnostic.message === "string" ? diagnostic.message : null;
405
- return message ? [`${kind}: ${message}`] : [];
406
- });
407
- return messages.length > 0 ? messages.join("; ") : null;
408
- }
409
- var serverReachabilityCache = new Map;
410
- async function probeServerReachability(baseUrl, authToken) {
411
- try {
412
- const response = await fetch(`${baseUrl.replace(/\/+$/, "")}/api/server/status`, {
413
- headers: mergeHeaders(undefined, authToken),
414
- signal: AbortSignal.timeout(1500)
415
- });
416
- return response.ok;
417
- } catch {
418
- return false;
419
- }
420
- }
421
- function cachedServerReachability(projectRoot, baseUrl, authToken) {
422
- const key = resolve4(projectRoot);
423
- const cached = serverReachabilityCache.get(key);
424
- if (cached)
425
- return cached;
426
- const probe = probeServerReachability(baseUrl, authToken);
427
- serverReachabilityCache.set(key, probe);
428
- return probe;
429
- }
430
- function describeSelectedServer(projectRoot, server) {
431
- try {
432
- const selected = resolveSelectedConnection(projectRoot);
433
- if (selected) {
434
- return {
435
- alias: selected.alias,
436
- target: selected.connection.kind === "remote" ? selected.connection.baseUrl : server.baseUrl
437
- };
438
- }
439
- } catch {}
440
- return { alias: server.connectionKind === "remote" ? "remote" : "local", target: server.baseUrl };
441
- }
442
- async function buildServerFailureContext(projectRoot, server) {
443
- const { alias, target } = describeSelectedServer(projectRoot, server);
444
- const reachable = await cachedServerReachability(projectRoot, server.baseUrl, server.authToken);
445
- const reachability = reachable ? "server is reachable" : "server is unreachable";
446
- return {
447
- contextLine: `Currently connected to: ${alias} at ${target} (${reachability}).`,
448
- hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
449
- };
450
- }
451
- async function requestServerJson(context, pathname, init = {}) {
452
- const server = await ensureServerForCli(context.projectRoot);
453
- const headers = mergeHeaders(init.headers, server.authToken);
454
- if (server.serverProjectRoot)
455
- headers.set("x-rig-project-root", server.serverProjectRoot);
456
- reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
457
- let response;
458
- try {
459
- response = await fetch(`${server.baseUrl}${pathname}`, {
460
- ...init,
461
- headers
462
- });
463
- } catch (error) {
464
- const failure = await buildServerFailureContext(context.projectRoot, server);
465
- throw new CliError(`Rig server request failed: ${error instanceof Error ? error.message : String(error)}
466
- ${failure.contextLine}`, 1, { hint: failure.hint });
467
- }
468
- const text = await response.text();
469
- const payload = text.trim().length > 0 ? (() => {
470
- try {
471
- return JSON.parse(text);
472
- } catch {
473
- return null;
474
- }
475
- })() : null;
476
- if (!response.ok) {
477
- const diagnostics = diagnosticMessage(payload);
478
- const rawDetail = diagnostics ?? (text || response.statusText);
479
- const detail = diagnostics ? rawDetail : rawDetail.split(`
480
- `).map((line) => line.trim()).find((line) => line.length > 0)?.slice(0, 200) ?? response.statusText;
481
- const failure = await buildServerFailureContext(context.projectRoot, server);
482
- throw new CliError(`Rig server request failed (${response.status}): ${detail}
483
- ${failure.contextLine}`, 1, { hint: failure.hint });
484
- }
485
- return payload;
486
- }
487
- var RESUMABLE_RUN_STATUSES = new Set([
488
- "created",
489
- "preparing",
490
- "running",
491
- "validating",
492
- "reviewing",
493
- "stopped",
494
- "failed",
495
- "needs-attention",
496
- "needs_attention"
497
- ]);
498
272
 
499
273
  // packages/cli/src/commands/_doctor-checks.ts
500
274
  function check(id, label, status, detail, remediation) {
@@ -515,31 +289,14 @@ function isAuthenticated(payload) {
515
289
  const record = payload;
516
290
  return record.signedIn === true || record.authenticated === true || record.status === "authenticated" || record.ok === true && typeof record.login === "string" && record.login.trim().length > 0;
517
291
  }
518
- function repoSlugFromConfig(config) {
519
- const project = config?.project;
520
- if (project && typeof project === "object" && !Array.isArray(project)) {
521
- const record = project;
522
- if (typeof record.repo === "string" && /^([^/\s]+)\/([^/\s]+)$/.test(record.repo))
523
- return record.repo;
524
- if (typeof record.name === "string" && /^([^/\s]+)\/([^/\s]+)$/.test(record.name))
525
- return record.name;
526
- }
527
- const taskSource = config?.taskSource;
528
- if (taskSource && typeof taskSource === "object" && !Array.isArray(taskSource)) {
529
- const source = taskSource;
530
- if (typeof source.owner === "string" && typeof source.repo === "string")
531
- return `${source.owner}/${source.repo}`;
532
- }
533
- return null;
534
- }
535
292
  function loadFallbackConfig(projectRoot) {
536
293
  const candidates = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
537
294
  for (const name of candidates) {
538
- const path = resolve5(projectRoot, name);
539
- if (!existsSync4(path))
295
+ const path = resolve4(projectRoot, name);
296
+ if (!existsSync3(path))
540
297
  continue;
541
298
  try {
542
- const source = readFileSync4(path, "utf8");
299
+ const source = readFileSync2(path, "utf8");
543
300
  if (name.endsWith(".json"))
544
301
  return JSON.parse(source);
545
302
  const owner = source.match(/owner\s*:\s*["']([^"']+)["']/)?.[1];
@@ -558,14 +315,11 @@ function loadFallbackConfig(projectRoot) {
558
315
  }
559
316
  return null;
560
317
  }
561
- function projectStatusSlug(projectRoot, config) {
562
- return readRepoConnection(projectRoot)?.project ?? repoSlugFromConfig(config);
563
- }
564
318
  function githubProjectsCheck(config) {
565
319
  const github = config?.github;
566
320
  const projects = github?.projects;
567
321
  if (!projects?.enabled) {
568
- return check("github-projects", "GitHub Projects status sync", "warn", "disabled or not configured", "Run `rig init --github-project <project>` or configure github.projects when Project status sync should be authoritative.");
322
+ return check("github-projects", "GitHub Projects status sync", "warn", "disabled or not configured", "Current OMP flow does not require GitHub Projects status sync; configure github.projects manually when Project status sync should be authoritative.");
569
323
  }
570
324
  if (projects.projectId && projects.statusFieldId) {
571
325
  return check("github-projects", "GitHub Projects status sync", "pass", `project ${projects.projectId}`);
@@ -590,16 +344,6 @@ function permissionAllowsPr(payload) {
590
344
  }
591
345
  return null;
592
346
  }
593
- function labelsReady(payload) {
594
- if (!payload || typeof payload !== "object" || Array.isArray(payload))
595
- return null;
596
- const record = payload;
597
- if (record.ok === true || record.ready === true || record.labelsReady === true)
598
- return true;
599
- if (record.ok === false || record.ready === false || record.labelsReady === false)
600
- return false;
601
- return null;
602
- }
603
347
  function prMergeCheck(config) {
604
348
  const pr = config?.pr;
605
349
  const merge = config?.merge;
@@ -613,7 +357,7 @@ async function runRigDoctorChecks(options) {
613
357
  const checks = [];
614
358
  const which = options.which ?? ((binary) => Bun.which(binary));
615
359
  const bunVersion = options.bunVersion ?? Bun.version;
616
- const request = options.requestJson ?? ((pathname, init) => requestServerJson({ projectRoot }, pathname, init));
360
+ const request = options.requestJson ?? ((pathname, init) => requestGitHubAuthJsonInProcess({ projectRoot }, pathname, init));
617
361
  const loadConfig = options.loadConfig ?? loadRigConfigOrNull;
618
362
  const progress = options.onProgress ?? (() => {});
619
363
  progress("Checking local toolchain\u2026");
@@ -621,78 +365,26 @@ async function runRigDoctorChecks(options) {
621
365
  progress("Loading rig.config\u2026");
622
366
  const loadedConfig = await loadConfig(projectRoot).catch(() => null);
623
367
  const config = loadedConfig ?? loadFallbackConfig(projectRoot);
624
- const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync4(resolve5(projectRoot, name)));
625
- checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "Run `rig init` or fix the config error."));
368
+ const hasConfigFile = ["rig.config.ts", "rig.config.mts", "rig.config.json"].some((name) => existsSync3(resolve4(projectRoot, name)));
369
+ checks.push(config ? check("config", "rig.config loadable", "pass") : check("config", "rig.config loadable", hasConfigFile ? "fail" : "fail", hasConfigFile ? "config file exists but failed to load" : "missing rig.config.ts/json", "Create/fix rig.config.ts or use the OMP cockpit Start tab to scaffold one."));
626
370
  const taskSourceKind = config?.taskSource?.kind;
627
371
  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."));
628
372
  const repo = readRepoConnection(projectRoot);
629
- 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>`."));
630
- const selected = (() => {
631
- try {
632
- return resolveSelectedConnection(projectRoot);
633
- } catch {
634
- return null;
635
- }
636
- })();
637
- 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));
638
- let server = null;
373
+ checks.push(repo ? check("project-link", "repo selected for local setup", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --repo owner/repo` if this project should use GitHub Issues.") : check("project-link", "repo selected for local setup", "warn", "missing .rig/state/connection.json", "Current UX can run without this compatibility file; `rig init` recreates it for GitHub-backed projects."));
639
374
  try {
640
- progress("Connecting to the selected Rig server\u2026");
641
- server = await (options.resolveServer ?? ensureServerForCli)(projectRoot);
642
- checks.push(check("server", "Rig server reachable", "pass", `${server.connectionKind} ${server.baseUrl}`));
375
+ progress("Checking GitHub auth\u2026");
376
+ const auth = await request("/api/github/auth/status");
377
+ 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>`."));
643
378
  } catch (error) {
644
- checks.push(check("server", "Rig server reachable", "fail", errorMessage(error), "Start the local Rig server or fix the selected remote connection."));
379
+ checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig."));
645
380
  }
646
- if (server || options.requestJson) {
647
- try {
648
- progress("Checking server status\u2026");
649
- const status = await request("/api/server/status");
650
- checks.push(check("server-status", "server project status", "pass", JSON.stringify(status).slice(0, 180)));
651
- } catch (error) {
652
- checks.push(check("server-status", "server project status", "fail", errorMessage(error), "Run `rig doctor` after the selected server is reachable."));
653
- }
654
- try {
655
- progress("Checking GitHub auth\u2026");
656
- const auth = await request("/api/github/auth/status");
657
- 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>`."));
658
- } catch (error) {
659
- checks.push(check("github-auth", "GitHub auth", "fail", errorMessage(error), "Authenticate GitHub through Rig and ensure the server exposes auth status."));
660
- }
661
- try {
662
- progress("Checking GitHub repo permissions\u2026");
663
- const permissions = await request("/api/github/repo/permissions");
664
- const allowed = permissionAllowsPr(permissions);
665
- 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."));
666
- } catch (error) {
667
- 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."));
668
- }
669
- try {
670
- progress("Checking GitHub issue labels\u2026");
671
- const labels = await request("/api/workspace/task-labels");
672
- const ready = labelsReady(labels);
673
- 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."));
674
- } catch (error) {
675
- checks.push(check("task-labels", "GitHub issue labels", "warn", errorMessage(error), "Run `rig init`/`rig doctor` after label setup is wired on the server."));
676
- }
677
- try {
678
- progress("Checking task projection\u2026");
679
- const projection = await request("/api/workspace/task-projection");
680
- checks.push(check("task-projection", "task projection", "pass", JSON.stringify(projection).slice(0, 180)));
681
- } catch (error) {
682
- checks.push(check("task-projection", "task projection", "warn", errorMessage(error), "Refresh task projection with `rig task list` or fix the task source."));
683
- }
684
- const slug = projectStatusSlug(projectRoot, config);
685
- if (slug) {
686
- try {
687
- progress("Checking server project checkout\u2026");
688
- const project = await request(`/api/projects/${encodeURIComponent(slug)}`);
689
- checks.push(check("remote-checkout", "server project checkout", "pass", JSON.stringify(project).slice(0, 180)));
690
- } catch (error) {
691
- checks.push(check("remote-checkout", "server project checkout", "warn", errorMessage(error), "Run `rig init --yes --repo owner/repo` to register/link the server project checkout."));
692
- }
693
- } else {
694
- checks.push(check("remote-checkout", "server project checkout", "warn", "repo slug unknown", "Set project.repo or run `rig init --repo owner/repo`."));
695
- }
381
+ try {
382
+ progress("Checking GitHub repo permissions\u2026");
383
+ const permissions = await request("/api/github/repo/permissions");
384
+ const allowed = permissionAllowsPr(permissions);
385
+ 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."));
386
+ } catch (error) {
387
+ checks.push(check("github-repo-permissions", "GitHub repo PR permissions", "warn", errorMessage(error), "Ensure the token can open PRs."));
696
388
  }
697
389
  if (taskSourceKind === "github-issues") {
698
390
  checks.push(check("gh", "gh CLI fallback", which("gh") ? "pass" : "warn", which("gh") ?? undefined, "Install gh for local/dev GitHub fallback operations."));
@@ -706,7 +398,7 @@ async function runRigDoctorChecks(options) {
706
398
  hint: errorMessage(error)
707
399
  }]);
708
400
  for (const pi of piChecks) {
709
- checks.push(check(pi.label === "pi" ? "pi" : "pi-rig", pi.label, pi.ok ? "pass" : "warn", pi.detail, pi.hint ?? (pi.ok ? undefined : "Run `rig init --yes` to install/update Pi and enable pi-rig.")));
401
+ checks.push(check(pi.label === "pi" ? "pi" : "pi-rig", pi.label, pi.ok ? "pass" : "warn", pi.detail, pi.hint ?? (pi.ok ? undefined : "Install Pi/OMP and the Rig extension, then use bare `rig` or Cockpit \u2192 Doctor to verify.")));
710
402
  }
711
403
  return checks;
712
404
  }
@@ -757,7 +449,7 @@ function createTtySpinner(input) {
757
449
  output.write("\r\x1B[2K");
758
450
  };
759
451
  render();
760
- const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
452
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 16) : null;
761
453
  return {
762
454
  setLabel(next) {
763
455
  label = next;
@@ -787,90 +479,20 @@ function createTtySpinner(input) {
787
479
  };
788
480
  }
789
481
 
790
- // packages/cli/src/app/theme.ts
791
- var RIG_PALETTE = {
792
- ink: "#f2f3f6",
793
- ink2: "#aeb0ba",
794
- ink3: "#6c6e79",
795
- ink4: "#44464f",
796
- accent: "#ccff4d",
797
- accentDim: "#a9d63f",
798
- cyan: "#56d8ff",
799
- red: "#ff5d5d",
800
- yellow: "#ffd24d"
801
- };
802
- function hexToRgb(hex) {
803
- const value = hex.replace("#", "");
804
- return [
805
- Number.parseInt(value.slice(0, 2), 16),
806
- Number.parseInt(value.slice(2, 4), 16),
807
- Number.parseInt(value.slice(4, 6), 16)
808
- ];
809
- }
810
- function fg(hex) {
811
- const [r, g, b] = hexToRgb(hex);
812
- return (text) => `\x1B[38;2;${r};${g};${b}m${text}\x1B[39m`;
813
- }
814
- var ink = fg(RIG_PALETTE.ink);
815
- var ink2 = fg(RIG_PALETTE.ink2);
816
- var ink3 = fg(RIG_PALETTE.ink3);
817
- var ink4 = fg(RIG_PALETTE.ink4);
818
- var accent = fg(RIG_PALETTE.accent);
819
- var accentDim = fg(RIG_PALETTE.accentDim);
820
- var cyan = fg(RIG_PALETTE.cyan);
821
- var red = fg(RIG_PALETTE.red);
822
- var yellow = fg(RIG_PALETTE.yellow);
823
- function bold(text) {
824
- return `\x1B[1m${text}\x1B[22m`;
825
- }
826
- var DRONE_ART = [
827
- " .-=-. .-=-. ",
828
- " ( !!! ) ( !!! ) ",
829
- " '-=-'._ _.'-=-' ",
830
- " '._ _.' ",
831
- " '=$$$$$$$=.' ",
832
- " =$$$$$$$$$$$= ",
833
- " $$$@@@@@@@@@@$$$ ",
834
- " $$$@@ @@$$$ ",
835
- " $$@ ? @$$$ ",
836
- " $$$@ '-' @$$$ ",
837
- " $$$@@ @@$$$ ",
838
- " $$$@@@@@@@@@@$$$ ",
839
- " =$$$$$$$$$$$= ",
840
- " '=$$$$$$$=.' ",
841
- " _.' '._ ",
842
- " .-=-.' '.-=-. ",
843
- " ( !!! ) ( !!! ) ",
844
- " '-=-' '-=-' "
845
- ];
846
- var EYE_FRAMES = ["@", "o", "."];
847
- var DRONE_WIDTH = DRONE_ART[0].length;
848
- var DRONE_HEIGHT = DRONE_ART.length;
849
- var MICRO_BLADES = ["---", "\\\\\\", "|||", "///"];
850
- function microDroneFrame(tick) {
851
- const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
852
- const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
853
- return `(${blade})${eye}(${blade})`;
854
- }
855
- var MICRO_DRONE_FRAMES = Array.from({ length: 12 }, (_, index) => microDroneFrame(index));
856
- function renderMicroDroneFrame(tick) {
857
- const blade = MICRO_BLADES[tick % MICRO_BLADES.length];
858
- const eye = EYE_FRAMES[Math.floor(tick / 2) % EYE_FRAMES.length];
859
- return `${ink4("(")}${cyan(blade)}${ink4(")")}${bold(accent(eye))}${ink4("(")}${cyan(blade)}${ink4(")")}`;
860
- }
861
-
862
482
  // packages/cli/src/commands/_async-ui.ts
483
+ var FRAMES = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
863
484
  var DONE_SYMBOL = pc.green("\u25C7");
864
485
  var FAIL_SYMBOL = pc.red("\u25A0");
865
486
  var activeUpdate = null;
866
487
  async function withSpinner(label, work, options = {}) {
867
488
  if (options.outputMode === "json") {
868
- return work(() => {});
489
+ return work(() => {
490
+ return;
491
+ });
869
492
  }
870
493
  if (activeUpdate) {
871
- const outer = activeUpdate;
872
- outer(label);
873
- return work(outer);
494
+ activeUpdate(label);
495
+ return work(activeUpdate);
874
496
  }
875
497
  const output = options.output ?? process.stderr;
876
498
  const isTty = output.isTTY === true;
@@ -882,26 +504,23 @@ async function withSpinner(label, work, options = {}) {
882
504
  lastLabel = next;
883
505
  };
884
506
  activeUpdate = update2;
885
- const previousListener2 = setServerPhaseListener(update2);
886
507
  try {
887
508
  return await work(update2);
888
509
  } finally {
889
510
  activeUpdate = null;
890
- setServerPhaseListener(previousListener2);
891
511
  }
892
512
  }
893
513
  const spinner = createTtySpinner({
894
514
  label,
895
515
  output,
896
- frames: MICRO_DRONE_FRAMES,
897
- styleFrame: (frame) => renderMicroDroneFrame(Math.max(0, MICRO_DRONE_FRAMES.indexOf(frame)))
516
+ frames: FRAMES,
517
+ styleFrame: (frame) => pc.cyan(frame)
898
518
  });
899
519
  const update = (next) => {
900
520
  lastLabel = next;
901
521
  spinner.setLabel(next);
902
522
  };
903
523
  activeUpdate = update;
904
- const previousListener = setServerPhaseListener(update);
905
524
  try {
906
525
  const result = await work(update);
907
526
  spinner.stop(options.doneLabel ? `${DONE_SYMBOL} ${options.doneLabel}` : undefined);
@@ -911,7 +530,6 @@ async function withSpinner(label, work, options = {}) {
911
530
  throw error;
912
531
  } finally {
913
532
  activeUpdate = null;
914
- setServerPhaseListener(previousListener);
915
533
  }
916
534
  }
917
535
 
@@ -983,8 +601,8 @@ function runSetupInit(projectRoot) {
983
601
  mkdirSync2(stateDir, { recursive: true });
984
602
  mkdirSync2(logsDir, { recursive: true });
985
603
  mkdirSync2(artifactsDir, { recursive: true });
986
- const failuresPath = resolve6(stateDir, "failed_approaches.md");
987
- if (!existsSync5(failuresPath)) {
604
+ const failuresPath = resolve5(stateDir, "failed_approaches.md");
605
+ if (!existsSync4(failuresPath)) {
988
606
  writeFileSync2(failuresPath, `# Failed Approaches
989
607
 
990
608
  `, "utf-8");
@@ -996,24 +614,24 @@ async function runSetupCheck(projectRoot, outputMode = "text") {
996
614
  console.log(formatDoctorChecks(doctorChecks));
997
615
  const failures = countDoctorFailures(doctorChecks);
998
616
  if (failures > 0) {
999
- throw new CliError(`Setup check failed (${failures} failing doctor check${failures === 1 ? "" : "s"}).`, 1, { hint: "Run `rig doctor` for the full check list with remediations." });
617
+ throw new CliError(`Setup check failed (${failures} failing doctor check${failures === 1 ? "" : "s"}).`, 1, { hint: "Legacy setup diagnostics failed; for current UX run bare `rig` and open Cockpit \u2192 Doctor for remediation details." });
1000
618
  }
1001
619
  return doctorChecks;
1002
620
  }
1003
621
  async function runSetupPreflight(projectRoot, outputMode = "text") {
1004
622
  await runSetupCheck(projectRoot, outputMode);
1005
- const validationRoot = resolve6(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
1006
- if (existsSync5(validationRoot)) {
623
+ const validationRoot = resolve5(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
624
+ if (existsSync4(validationRoot)) {
1007
625
  const validators = readdirSync(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
1008
626
  for (const validator of validators) {
1009
- const script = resolve6(validationRoot, validator.name, "validate.sh");
1010
- if (existsSync5(script)) {
627
+ const script = resolve5(validationRoot, validator.name, "validate.sh");
628
+ if (existsSync4(script)) {
1011
629
  console.log(`OK: validator script ${script}`);
1012
630
  }
1013
631
  }
1014
632
  }
1015
- const hooksRoot = resolve6(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
1016
- if (existsSync5(hooksRoot)) {
633
+ const hooksRoot = resolve5(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
634
+ if (existsSync4(hooksRoot)) {
1017
635
  const hooks = readdirSync(hooksRoot).filter((name) => name.endsWith(".sh"));
1018
636
  for (const hook of hooks) {
1019
637
  console.log(`OK: hook ${hook}`);