@h-rig/cli 0.0.6-alpha.82 → 0.0.6-alpha.83

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 (100) hide show
  1. package/dist/bin/build-rig-binaries.js +40 -8
  2. package/dist/bin/rig.js +2798 -1440
  3. package/dist/src/app/board.js +62 -13
  4. package/dist/src/app-opentui/adapters/command.d.ts +2 -0
  5. package/dist/src/app-opentui/adapters/command.js +329 -0
  6. package/dist/src/app-opentui/adapters/common.js +2 -2
  7. package/dist/src/app-opentui/adapters/doctor.js +63 -14
  8. package/dist/src/app-opentui/adapters/fleet.js +84 -20
  9. package/dist/src/app-opentui/adapters/inbox.js +83 -19
  10. package/dist/src/app-opentui/adapters/init.js +87 -23
  11. package/dist/src/app-opentui/adapters/pi-attach.js +96 -34
  12. package/dist/src/app-opentui/adapters/run-detail.js +83 -19
  13. package/dist/src/app-opentui/adapters/server.js +100 -23
  14. package/dist/src/app-opentui/adapters/tasks.d.ts +11 -0
  15. package/dist/src/app-opentui/adapters/tasks.js +742 -94
  16. package/dist/src/app-opentui/bootstrap.d.ts +1 -6
  17. package/dist/src/app-opentui/bootstrap.js +13769 -12368
  18. package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
  19. package/dist/src/app-opentui/command-pty-host.js +248 -0
  20. package/dist/src/app-opentui/events.js +1 -1
  21. package/dist/src/app-opentui/focus-manager.d.ts +14 -0
  22. package/dist/src/app-opentui/focus-manager.js +24 -0
  23. package/dist/src/app-opentui/index.js +3802 -2882
  24. package/dist/src/app-opentui/intent.js +154 -48
  25. package/dist/src/app-opentui/keymap.d.ts +20 -0
  26. package/dist/src/app-opentui/keymap.js +707 -0
  27. package/dist/src/app-opentui/launch-routing.d.ts +16 -0
  28. package/dist/src/app-opentui/launch-routing.js +55 -0
  29. package/dist/src/app-opentui/layout.js +2 -2
  30. package/dist/src/app-opentui/pi-host-child.js +66 -16
  31. package/dist/src/app-opentui/pi-pty-host.d.ts +9 -0
  32. package/dist/src/app-opentui/pi-pty-host.js +9 -11
  33. package/dist/src/app-opentui/registry.js +3231 -2403
  34. package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
  35. package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
  36. package/dist/src/app-opentui/render/graphics.d.ts +1 -1
  37. package/dist/src/app-opentui/render/graphics.js +131 -16
  38. package/dist/src/app-opentui/render/image-visual-layer-worker.js +408 -957
  39. package/dist/src/app-opentui/render/image-visual-layer.d.ts +18 -10
  40. package/dist/src/app-opentui/render/image-visual-layer.js +386 -356
  41. package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
  42. package/dist/src/app-opentui/render/panel-layout.js +48 -0
  43. package/dist/src/app-opentui/render/panels.d.ts +2 -0
  44. package/dist/src/app-opentui/render/panels.js +62 -29
  45. package/dist/src/app-opentui/render/preloader.d.ts +10 -0
  46. package/dist/src/app-opentui/render/preloader.js +163 -0
  47. package/dist/src/app-opentui/render/scene.d.ts +3 -0
  48. package/dist/src/app-opentui/render/scene.js +12 -0
  49. package/dist/src/app-opentui/render/text.js +5 -1
  50. package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
  51. package/dist/src/app-opentui/render/type-bar.js +51 -16
  52. package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
  53. package/dist/src/app-opentui/runtime-resources.js +62 -0
  54. package/dist/src/app-opentui/runtime.js +2322 -1513
  55. package/dist/src/app-opentui/scenes/command.d.ts +3 -0
  56. package/dist/src/app-opentui/scenes/command.js +103 -0
  57. package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
  58. package/dist/src/app-opentui/scenes/doctor.js +53 -14
  59. package/dist/src/app-opentui/scenes/error.js +44 -14
  60. package/dist/src/app-opentui/scenes/fleet.js +40 -21
  61. package/dist/src/app-opentui/scenes/handoff.js +142 -27
  62. package/dist/src/app-opentui/scenes/help.js +63 -48
  63. package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
  64. package/dist/src/app-opentui/scenes/inbox.js +64 -17
  65. package/dist/src/app-opentui/scenes/init.d.ts +2 -1
  66. package/dist/src/app-opentui/scenes/init.js +62 -21
  67. package/dist/src/app-opentui/scenes/main.d.ts +2 -1
  68. package/dist/src/app-opentui/scenes/main.js +80 -24
  69. package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
  70. package/dist/src/app-opentui/scenes/run-detail.js +39 -25
  71. package/dist/src/app-opentui/scenes/server.d.ts +2 -1
  72. package/dist/src/app-opentui/scenes/server.js +71 -20
  73. package/dist/src/app-opentui/scenes/tasks.js +44 -22
  74. package/dist/src/app-opentui/state.js +70 -30
  75. package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
  76. package/dist/src/app-opentui/terminal-capabilities.js +15 -0
  77. package/dist/src/app-opentui/types.d.ts +10 -2
  78. package/dist/src/commands/_doctor-checks.js +62 -13
  79. package/dist/src/commands/_operator-view.js +63 -13
  80. package/dist/src/commands/_pi-frontend.js +63 -13
  81. package/dist/src/commands/_preflight.js +64 -14
  82. package/dist/src/commands/_server-client.js +82 -18
  83. package/dist/src/commands/_snapshot-upload.js +62 -13
  84. package/dist/src/commands/connect.js +7 -1
  85. package/dist/src/commands/doctor.js +62 -13
  86. package/dist/src/commands/github.js +144 -23
  87. package/dist/src/commands/inbox.js +62 -13
  88. package/dist/src/commands/init.js +82 -18
  89. package/dist/src/commands/inspect.js +62 -13
  90. package/dist/src/commands/run.js +66 -13
  91. package/dist/src/commands/server.js +69 -14
  92. package/dist/src/commands/setup.js +62 -13
  93. package/dist/src/commands/stats.js +62 -13
  94. package/dist/src/commands/task-run-driver.js +62 -13
  95. package/dist/src/commands/task.js +65 -14
  96. package/dist/src/commands.js +227 -92
  97. package/dist/src/index.js +234 -99
  98. package/package.json +8 -9
  99. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
  100. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +0 -1484
package/dist/src/index.js CHANGED
@@ -1105,17 +1105,21 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
1105
1105
  const scopedKey = resolve11(projectRoot ?? process.cwd());
1106
1106
  scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
1107
1107
  }
1108
- function readPrivateRemoteSessionToken(projectRoot) {
1108
+ function readRemoteAuthState(projectRoot) {
1109
1109
  const path = resolve11(projectRoot, ".rig", "state", "github-auth.json");
1110
1110
  if (!existsSync7(path))
1111
1111
  return null;
1112
1112
  try {
1113
1113
  const parsed = JSON.parse(readFileSync4(path, "utf8"));
1114
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
1114
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
1115
1115
  } catch {
1116
1116
  return null;
1117
1117
  }
1118
1118
  }
1119
+ function readPrivateRemoteSessionToken(projectRoot) {
1120
+ const parsed = readRemoteAuthState(projectRoot);
1121
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
1122
+ }
1119
1123
  function readGitHubBearerTokenForRemote(projectRoot) {
1120
1124
  const scopedKey = resolve11(projectRoot);
1121
1125
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -1126,15 +1130,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
1126
1130
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
1127
1131
  }
1128
1132
  function readStoredGitHubAuthToken(projectRoot) {
1129
- const path = resolve11(projectRoot, ".rig", "state", "github-auth.json");
1130
- if (!existsSync7(path))
1133
+ const parsed = readRemoteAuthState(projectRoot);
1134
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
1135
+ }
1136
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
1137
+ const repo = readRepoConnection(projectRoot);
1138
+ const slug = repo?.project?.trim();
1139
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
1131
1140
  return null;
1132
- try {
1133
- const parsed = JSON.parse(readFileSync4(path, "utf8"));
1134
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
1135
- } catch {
1141
+ const auth = readRemoteAuthState(projectRoot);
1142
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
1143
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
1144
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
1136
1145
  return null;
1137
- }
1146
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
1147
+ if (!checkoutBaseDir)
1148
+ return null;
1149
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
1150
+ writeRepoServerProjectRoot(projectRoot, inferred);
1151
+ return inferred;
1138
1152
  }
1139
1153
  function readLocalConnectionFallbackToken(projectRoot) {
1140
1154
  return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
@@ -1145,7 +1159,7 @@ async function ensureServerForCli(projectRoot) {
1145
1159
  if (selected?.connection.kind === "remote") {
1146
1160
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
1147
1161
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
1148
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
1162
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
1149
1163
  return {
1150
1164
  baseUrl: selected.connection.baseUrl,
1151
1165
  authToken,
@@ -1174,7 +1188,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
1174
1188
  if (!slug)
1175
1189
  return null;
1176
1190
  try {
1177
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
1191
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
1192
+ if (authToken && queryAuthFallbackEnabled())
1193
+ url.searchParams.set("rt", authToken);
1194
+ const response = await fetch(url, {
1178
1195
  headers: mergeHeaders(undefined, authToken)
1179
1196
  });
1180
1197
  if (!response.ok)
@@ -1201,10 +1218,23 @@ function appendTaskFilterParams(url, filters) {
1201
1218
  if (filters.limit !== undefined)
1202
1219
  url.searchParams.set("limit", String(filters.limit));
1203
1220
  }
1221
+ function mergeCookie(existing, name, value) {
1222
+ const encoded = `${name}=${encodeURIComponent(value)}`;
1223
+ if (!existing?.trim())
1224
+ return encoded;
1225
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
1226
+ return [...parts, encoded].join("; ");
1227
+ }
1228
+ function queryAuthFallbackEnabled(env = process.env) {
1229
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
1230
+ }
1204
1231
  function mergeHeaders(headers, authToken) {
1205
1232
  const merged = new Headers(headers);
1206
1233
  if (authToken) {
1207
- merged.set("authorization", `Bearer ${authToken}`);
1234
+ const bearer = `Bearer ${authToken}`;
1235
+ merged.set("authorization", bearer);
1236
+ merged.set("x-auth", bearer);
1237
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
1208
1238
  }
1209
1239
  return merged;
1210
1240
  }
@@ -1264,15 +1294,34 @@ async function buildServerFailureContext(projectRoot, server) {
1264
1294
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
1265
1295
  };
1266
1296
  }
1297
+ function isLoopbackRemoteBaseUrl(baseUrl) {
1298
+ try {
1299
+ const host = new URL(baseUrl).hostname.toLowerCase();
1300
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
1301
+ } catch {
1302
+ return false;
1303
+ }
1304
+ }
1305
+ function canUseRemoteWithoutProjectRoot(pathname) {
1306
+ return pathname === "/health" || pathname === "/api/health" || pathname === "/api/server/status" || pathname === "/api/server/project-root" || pathname.startsWith("/api/github/auth/") || pathname === "/api/projects" || pathname.startsWith("/api/projects/");
1307
+ }
1267
1308
  async function requestServerJson(context, pathname, init = {}) {
1268
1309
  const server = await ensureServerForCli(context.projectRoot);
1310
+ const requestUrl = new URL(`${server.baseUrl}${pathname}`);
1311
+ if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
1312
+ const repo = readRepoConnection(context.projectRoot);
1313
+ throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
1314
+ }
1269
1315
  const headers = mergeHeaders(init.headers, server.authToken);
1270
1316
  if (server.serverProjectRoot)
1271
1317
  headers.set("x-rig-project-root", server.serverProjectRoot);
1318
+ if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
1319
+ requestUrl.searchParams.set("rt", server.authToken);
1320
+ }
1272
1321
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
1273
1322
  let response;
1274
1323
  try {
1275
- response = await fetch(`${server.baseUrl}${pathname}`, {
1324
+ response = await fetch(requestUrl, {
1276
1325
  ...init,
1277
1326
  headers
1278
1327
  });
@@ -1334,11 +1383,26 @@ async function getGitHubAuthStatusViaServer(context) {
1334
1383
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
1335
1384
  }
1336
1385
  async function postGitHubTokenViaServer(context, token, options = {}) {
1337
- const payload = await requestServerJson(context, "/api/github/auth/token", {
1338
- method: "POST",
1339
- headers: { "content-type": "application/json" },
1340
- body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot })
1341
- });
1386
+ const server = await ensureServerForCli(context.projectRoot);
1387
+ const requestUrl = new URL(`${server.baseUrl}/api/github/auth/token`);
1388
+ reportServerPhase("POST /api/github/auth/token\u2026");
1389
+ let response;
1390
+ try {
1391
+ response = await fetch(requestUrl, {
1392
+ method: "POST",
1393
+ headers: { "content-type": "application/json" },
1394
+ body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
1395
+ });
1396
+ } catch (error) {
1397
+ const failure = await buildServerFailureContext(context.projectRoot, server);
1398
+ throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
1399
+ ${failure.contextLine}`, 1, { hint: failure.hint });
1400
+ }
1401
+ const payload = await response.json().catch(() => null);
1402
+ if (!response.ok) {
1403
+ const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
1404
+ throw new CliError(`Rig server auth bootstrap failed (${response.status}): ${detail}`, 1, { hint: "Re-run `rig github auth import-gh`, or check the selected server with `rig server status`." });
1405
+ }
1342
1406
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
1343
1407
  }
1344
1408
  async function prepareRemoteCheckoutViaServer(context, input) {
@@ -1669,7 +1733,8 @@ async function runFastTaskRunPreflight(context, options = {}) {
1669
1733
  }
1670
1734
  }
1671
1735
  const repo = readRepoConnection(context.projectRoot);
1672
- checks.push(repo ? preflightCheck("project-link", "project linked to Rig server", repo.project ? "pass" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : ""}`, "Run `rig init --yes --repo owner/repo` to record the GitHub repo slug.") : preflightCheck("project-link", "project linked to Rig server", legacyServerCompatibility ? "warn" : "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
1736
+ const remoteWithoutProjectLink = selectedServer?.connectionKind === "remote" && !repo?.project;
1737
+ checks.push(repo ? preflightCheck("project-link", "project linked to selected server", repo.project ? "pass" : remoteWithoutProjectLink ? "fail" : "warn", `${repo.selected}${repo.project ? ` -> ${repo.project}` : " (missing project link)"}`, remoteWithoutProjectLink ? "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to restore the remote project link." : "Run `rig init --yes --repo owner/repo` to record the GitHub repo slug.") : preflightCheck("project-link", "project linked to selected server", legacyServerCompatibility ? "warn" : "fail", "missing .rig/state/connection.json", "Run `rig init` or `rig server use <alias|local>`."));
1673
1738
  try {
1674
1739
  const auth = await request("/api/github/auth/status");
1675
1740
  checks.push(isAuthenticated(auth) ? preflightCheck("github-auth", "GitHub auth valid", "pass") : preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", "not authenticated", "Run `rig github auth import-gh` or `rig github auth token --token <token>`."));
@@ -2713,7 +2778,7 @@ var init__operator_surface = __esm(() => {
2713
2778
  });
2714
2779
 
2715
2780
  // packages/cli/src/commands/_pi-frontend.ts
2716
- import { existsSync as existsSync15, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
2781
+ import { existsSync as existsSync15, mkdirSync as mkdirSync10, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "fs";
2717
2782
  import { homedir as homedir6, tmpdir } from "os";
2718
2783
  import { join as join3 } from "path";
2719
2784
  import { main as runPiMain } from "@earendil-works/pi-coding-agent";
@@ -2748,7 +2813,7 @@ function buildOperatorPiEnv(input) {
2748
2813
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
2749
2814
  const server = await ensureServerForCli(context.projectRoot);
2750
2815
  const localCwd = join3(homedir6(), ".rig", "drones", runId.slice(0, 8));
2751
- mkdirSync9(localCwd, { recursive: true });
2816
+ mkdirSync10(localCwd, { recursive: true });
2752
2817
  trustDroneCwd(localCwd);
2753
2818
  installRigPiTheme();
2754
2819
  let sessionFileArg = [];
@@ -2770,7 +2835,7 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
2770
2835
  return line;
2771
2836
  }).join(`
2772
2837
  `);
2773
- writeFileSync6(localSessionPath, content);
2838
+ writeFileSync7(localSessionPath, content);
2774
2839
  sessionFileArg = ["--session", localSessionPath];
2775
2840
  }
2776
2841
  } catch {}
@@ -2779,12 +2844,12 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
2779
2844
  function trustDroneCwd(localCwd) {
2780
2845
  try {
2781
2846
  const agentDir = join3(homedir6(), ".pi", "agent");
2782
- mkdirSync9(agentDir, { recursive: true });
2847
+ mkdirSync10(agentDir, { recursive: true });
2783
2848
  const trustPath = join3(agentDir, "trust.json");
2784
2849
  const store = existsSync15(trustPath) ? JSON.parse(readFileSync10(trustPath, "utf8")) : {};
2785
2850
  if (store[localCwd] !== true) {
2786
2851
  store[localCwd] = true;
2787
- writeFileSync6(trustPath, `${JSON.stringify(store, null, "\t")}
2852
+ writeFileSync7(trustPath, `${JSON.stringify(store, null, "\t")}
2788
2853
  `);
2789
2854
  }
2790
2855
  } catch {}
@@ -2792,12 +2857,12 @@ function trustDroneCwd(localCwd) {
2792
2857
  function installRigPiTheme() {
2793
2858
  try {
2794
2859
  const themesDir = join3(homedir6(), ".pi", "agent", "themes");
2795
- mkdirSync9(themesDir, { recursive: true });
2860
+ mkdirSync10(themesDir, { recursive: true });
2796
2861
  const themePath = join3(themesDir, "rig.json");
2797
2862
  const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
2798
2863
  `;
2799
2864
  if (!existsSync15(themePath) || readFileSync10(themePath, "utf8") !== next) {
2800
- writeFileSync6(themePath, next);
2865
+ writeFileSync7(themePath, next);
2801
2866
  }
2802
2867
  } catch {}
2803
2868
  }
@@ -2817,6 +2882,7 @@ async function attachRunBundledPiFrontend(context, input) {
2817
2882
  let detached = false;
2818
2883
  try {
2819
2884
  await runPiMain([
2885
+ "--offline",
2820
2886
  "--no-extensions",
2821
2887
  "--no-skills",
2822
2888
  "--no-prompt-templates",
@@ -3487,7 +3553,7 @@ var init__task_picker = __esm(() => {
3487
3553
  // packages/cli/src/commands/task.ts
3488
3554
  import { readFileSync as readFileSync11 } from "fs";
3489
3555
  import { spawnSync as spawnSync3 } from "child_process";
3490
- import { resolve as resolve22 } from "path";
3556
+ import { resolve as resolve23 } from "path";
3491
3557
  import {
3492
3558
  taskArtifactDir,
3493
3559
  taskArtifacts,
@@ -3765,7 +3831,7 @@ async function executeTask(context, args, options) {
3765
3831
  const fileFlag = takeOption(rest.slice(1), "--file");
3766
3832
  let content;
3767
3833
  if (fileFlag.value) {
3768
- content = readFileSync11(resolve22(context.projectRoot, fileFlag.value), "utf-8");
3834
+ content = readFileSync11(resolve23(context.projectRoot, fileFlag.value), "utf-8");
3769
3835
  } else {
3770
3836
  content = await readStdin();
3771
3837
  }
@@ -4846,11 +4912,11 @@ async function runOperatorBoard(context, options = {}) {
4846
4912
  }, BOARD_REFRESH_MS);
4847
4913
  tui.start();
4848
4914
  refresh({ quiet: true });
4849
- await new Promise((resolve25) => {
4915
+ await new Promise((resolve26) => {
4850
4916
  const poll = setInterval(() => {
4851
4917
  if (stopped) {
4852
4918
  clearInterval(poll);
4853
- resolve25();
4919
+ resolve26();
4854
4920
  }
4855
4921
  }, 50);
4856
4922
  });
@@ -4884,7 +4950,7 @@ import {
4884
4950
  existsSync as existsSync19,
4885
4951
  readFileSync as readFileSync13
4886
4952
  } from "fs";
4887
- import { resolve as resolve25 } from "path";
4953
+ import { resolve as resolve26 } from "path";
4888
4954
  import { readBuildConfig } from "@rig/runtime/build-time-config";
4889
4955
 
4890
4956
  // packages/cli/src/commands/browser.ts
@@ -9112,14 +9178,64 @@ Usage: rig init`, 1);
9112
9178
  // packages/cli/src/commands/github.ts
9113
9179
  init_runner();
9114
9180
  init__server_client();
9181
+ init__connection_state();
9115
9182
  init__async_ui();
9116
9183
  import { spawnSync as spawnSync2 } from "child_process";
9184
+ import { mkdirSync as mkdirSync9, writeFileSync as writeFileSync6 } from "fs";
9185
+ import { dirname as dirname4, resolve as resolve19 } from "path";
9117
9186
  function printPayload(context, payload, fallback) {
9118
9187
  if (context.outputMode === "json")
9119
9188
  console.log(JSON.stringify(payload, null, 2));
9120
9189
  else
9121
9190
  console.log(fallback);
9122
9191
  }
9192
+ function apiSessionTokenFrom2(payload) {
9193
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
9194
+ return null;
9195
+ const token = payload.apiSessionToken;
9196
+ return typeof token === "string" && token.trim() ? token.trim() : null;
9197
+ }
9198
+ function payloadString(payload, key) {
9199
+ const value = payload[key];
9200
+ return typeof value === "string" && value.trim() ? value.trim() : null;
9201
+ }
9202
+ function payloadRecord(payload, key) {
9203
+ const value = payload[key];
9204
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
9205
+ }
9206
+ function remoteNamespaceMetadata(result) {
9207
+ const namespace = payloadRecord(result, "userNamespace");
9208
+ return {
9209
+ ...payloadString(result, "login") ? { login: payloadString(result, "login") } : {},
9210
+ ...payloadString(result, "userId") ? { userId: payloadString(result, "userId") } : {},
9211
+ ...namespace && payloadString(namespace, "key") ? { userNamespaceKey: payloadString(namespace, "key") } : {},
9212
+ ...namespace && payloadString(namespace, "root") ? { userNamespaceRoot: payloadString(namespace, "root") } : {},
9213
+ ...namespace && payloadString(namespace, "checkoutBaseDir") ? { checkoutBaseDir: payloadString(namespace, "checkoutBaseDir") } : {},
9214
+ ...namespace && payloadString(namespace, "snapshotBaseDir") ? { snapshotBaseDir: payloadString(namespace, "snapshotBaseDir") } : {}
9215
+ };
9216
+ }
9217
+ function persistRemoteAuthSession(context, source, result, fallbackToken) {
9218
+ const apiSessionToken = apiSessionTokenFrom2(result);
9219
+ setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? fallbackToken, context.projectRoot);
9220
+ if (!apiSessionToken)
9221
+ return;
9222
+ const repo = readRepoConnection(context.projectRoot);
9223
+ const path = resolve19(context.projectRoot, ".rig", "state", "github-auth.json");
9224
+ mkdirSync9(dirname4(path), { recursive: true });
9225
+ writeFileSync6(path, `${JSON.stringify({
9226
+ authenticated: true,
9227
+ source,
9228
+ storedOnServer: true,
9229
+ ...repo?.project ? { selectedRepo: repo.project } : {},
9230
+ ...remoteNamespaceMetadata(result),
9231
+ apiSessionToken,
9232
+ updatedAt: new Date().toISOString()
9233
+ }, null, 2)}
9234
+ `, "utf8");
9235
+ }
9236
+ function isSignedIn(status) {
9237
+ return status.signedIn === true || status.authenticated === true;
9238
+ }
9123
9239
  function readGhToken() {
9124
9240
  const result = spawnSync2("gh", ["auth", "token"], { encoding: "utf8" });
9125
9241
  if (result.status !== 0) {
@@ -9141,7 +9257,7 @@ async function executeGithub(context, args) {
9141
9257
  if (rest.length > 0)
9142
9258
  throw new CliError("Usage: rig github auth status", 1);
9143
9259
  const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
9144
- printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
9260
+ printPayload(context, status, `GitHub auth: ${isSignedIn(status) ? "authenticated" : "unauthenticated"}`);
9145
9261
  return { ok: true, group: "github", command: "auth status", details: status };
9146
9262
  }
9147
9263
  case "token": {
@@ -9151,16 +9267,20 @@ async function executeGithub(context, args) {
9151
9267
  const token = parsed.value?.trim();
9152
9268
  if (!token)
9153
9269
  throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
9154
- const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
9155
- printPayload(context, result, "GitHub token stored on the selected Rig server.");
9270
+ const repo = readRepoConnection(context.projectRoot);
9271
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token, repo?.project ? { selectedRepo: repo.project } : {}), { outputMode: context.outputMode });
9272
+ persistRemoteAuthSession(context, "token", result, token);
9273
+ printPayload(context, result, "GitHub token stored on the selected server.");
9156
9274
  return { ok: true, group: "github", command: "auth token", details: result };
9157
9275
  }
9158
9276
  case "import-gh": {
9159
9277
  if (rest.length > 0)
9160
9278
  throw new CliError("Usage: rig github auth import-gh", 1);
9161
9279
  const importedToken = readGhToken();
9162
- const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
9163
- printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
9280
+ const repo = readRepoConnection(context.projectRoot);
9281
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken, repo?.project ? { selectedRepo: repo.project } : {}), { outputMode: context.outputMode });
9282
+ persistRemoteAuthSession(context, "gh", result, importedToken);
9283
+ printPayload(context, result, "GitHub token imported from gh and stored on the selected server.");
9164
9284
  return { ok: true, group: "github", command: "auth import-gh", details: result };
9165
9285
  }
9166
9286
  default:
@@ -9190,7 +9310,7 @@ init_runner();
9190
9310
  init__authority_runs();
9191
9311
  init__paths();
9192
9312
  import { readFileSync as readFileSync8 } from "fs";
9193
- import { resolve as resolve19 } from "path";
9313
+ import { resolve as resolve20 } from "path";
9194
9314
  import {
9195
9315
  appendRunJournalEvent,
9196
9316
  appendRunLogEntry,
@@ -9227,7 +9347,7 @@ function touchAuthorityRun(projectRoot, runId) {
9227
9347
  if (!current) {
9228
9348
  return;
9229
9349
  }
9230
- writeJsonFile3(resolve19(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
9350
+ writeJsonFile3(resolve20(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
9231
9351
  ...current,
9232
9352
  updatedAt: new Date().toISOString()
9233
9353
  });
@@ -9465,7 +9585,7 @@ init_runner();
9465
9585
  init__server_client();
9466
9586
  init__async_ui();
9467
9587
  import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
9468
- import { resolve as resolve20 } from "path";
9588
+ import { resolve as resolve21 } from "path";
9469
9589
  import {
9470
9590
  listAuthorityRuns,
9471
9591
  readAuthorityRun as readAuthorityRun3,
@@ -9509,7 +9629,7 @@ async function executeInspect(context, args) {
9509
9629
  }
9510
9630
  return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: fallback.runId, source: "server", entries } };
9511
9631
  }
9512
- const logsPath = resolve20(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
9632
+ const logsPath = resolve21(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
9513
9633
  if (!existsSync13(logsPath)) {
9514
9634
  throw new CliError(`No logs found for run ${latestRun.runId}.`, 1, { hint: `Try \`rig run show ${latestRun.runId}\` or \`rig run replay ${latestRun.runId}\`.` });
9515
9635
  }
@@ -9597,7 +9717,7 @@ async function executeInspect(context, args) {
9597
9717
  return { ok: true, group: "inspect", command };
9598
9718
  case "audit": {
9599
9719
  requireNoExtraArgs(rest, "rig inspect audit");
9600
- const auditPath = resolve20(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
9720
+ const auditPath = resolve21(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
9601
9721
  if (!existsSync13(auditPath)) {
9602
9722
  console.log("No audit log found.");
9603
9723
  } else {
@@ -10256,7 +10376,7 @@ import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/co
10256
10376
 
10257
10377
  // packages/cli/src/commands/_run-replay.ts
10258
10378
  import { existsSync as existsSync14, readdirSync as readdirSync2 } from "fs";
10259
- import { join as join2, resolve as resolve21 } from "path";
10379
+ import { join as join2, resolve as resolve22 } from "path";
10260
10380
  import {
10261
10381
  readAuthorityRun as readAuthorityRun4,
10262
10382
  readJsonlFile as readJsonlFile3,
@@ -10349,7 +10469,7 @@ function resolveRunSessionFile(record) {
10349
10469
  const sessionId = text(piSession.sessionId);
10350
10470
  if (!cwd || !sessionId)
10351
10471
  return null;
10352
- const sessionDir = resolve21(cwd, ".rig", "session");
10472
+ const sessionDir = resolve22(cwd, ".rig", "session");
10353
10473
  try {
10354
10474
  const match = readdirSync2(sessionDir).find((name) => name.endsWith(`_${sessionId}.jsonl`));
10355
10475
  return match ? join2(sessionDir, match) : null;
@@ -10847,6 +10967,9 @@ async function executeRun(context, args) {
10847
10967
  console.log(`Stop requested: ${runId}`);
10848
10968
  return { ok: true, group: "run", command, details: stopped };
10849
10969
  }
10970
+ if (isRemoteConnectionSelected(context.projectRoot)) {
10971
+ throw new CliError("Remote run stop requires an explicit run id.", 2, { hint: "Run `rig run list`, then `rig run stop <run-id>`." });
10972
+ }
10850
10973
  const result = await runStop(context.projectRoot);
10851
10974
  if (result.remaining.length > 0) {
10852
10975
  throw new CliError(`Failed to stop run(s): ${result.remaining.join(", ")}`, 1, { hint: "Check `rig run status`, then retry `rig run stop <run-id>` for the remaining runs." });
@@ -10963,7 +11086,13 @@ async function executeConnectionCommand(context, args, options) {
10963
11086
  if (!state.connections[alias])
10964
11087
  throw new CliError(`Unknown Rig server: ${alias}`, 1, { hint: "Run `rig server list` to see saved aliases, or save one with `rig server add <alias> <url>`." });
10965
11088
  }
10966
- const repoState = { selected: alias, linkedAt: new Date().toISOString() };
11089
+ const previousRepo = readRepoConnection(context.projectRoot);
11090
+ const repoState = {
11091
+ selected: alias,
11092
+ ...previousRepo?.project ? { project: previousRepo.project } : {},
11093
+ linkedAt: new Date().toISOString(),
11094
+ ...previousRepo?.serverProjectRoot && previousRepo.selected === alias ? { serverProjectRoot: previousRepo.serverProjectRoot } : {}
11095
+ };
10967
11096
  writeRepoConnection(context.projectRoot, repoState);
10968
11097
  printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
10969
11098
  ["selected", alias],
@@ -11198,8 +11327,8 @@ init_task();
11198
11327
 
11199
11328
  // packages/cli/src/commands/task-run-driver.ts
11200
11329
  init_runner();
11201
- import { copyFileSync as copyFileSync3, existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
11202
- import { resolve as resolve23 } from "path";
11330
+ import { copyFileSync as copyFileSync3, existsSync as existsSync16, mkdirSync as mkdirSync11, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync8 } from "fs";
11331
+ import { resolve as resolve24 } from "path";
11203
11332
  import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
11204
11333
  import { createInterface as createLineInterface } from "readline";
11205
11334
  import { loadConfig as loadConfig2 } from "@rig/core/load-config";
@@ -11298,12 +11427,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
11298
11427
  return 0;
11299
11428
  let copied = 0;
11300
11429
  for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
11301
- const sourcePath = resolve23(sourceRoot, relativePath);
11302
- const targetPath = resolve23(targetRoot, relativePath);
11430
+ const sourcePath = resolve24(sourceRoot, relativePath);
11431
+ const targetPath = resolve24(targetRoot, relativePath);
11303
11432
  try {
11304
11433
  if (!statSync2(sourcePath).isFile())
11305
11434
  continue;
11306
- mkdirSync10(resolve23(targetPath, ".."), { recursive: true });
11435
+ mkdirSync11(resolve24(targetPath, ".."), { recursive: true });
11307
11436
  copyFileSync3(sourcePath, targetPath);
11308
11437
  copied += 1;
11309
11438
  } catch {}
@@ -11342,7 +11471,7 @@ function buildDirtyBaselineHandshakeEnv(input) {
11342
11471
  return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
11343
11472
  return {
11344
11473
  RIG_BASELINE_MODE: "dirty-snapshot",
11345
- RIG_DIRTY_BASELINE_READY_FILE: resolve23(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
11474
+ RIG_DIRTY_BASELINE_READY_FILE: resolve24(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
11346
11475
  };
11347
11476
  }
11348
11477
  function positiveInt(value, fallback) {
@@ -11447,9 +11576,9 @@ function createCommandRunner(binary) {
11447
11576
  const stderrChunks = [];
11448
11577
  child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
11449
11578
  child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
11450
- return await new Promise((resolve24) => {
11451
- child.once("error", (error) => resolve24({ exitCode: 1, stderr: error.message }));
11452
- child.once("close", (code) => resolve24({
11579
+ return await new Promise((resolve25) => {
11580
+ child.once("error", (error) => resolve25({ exitCode: 1, stderr: error.message }));
11581
+ child.once("close", (code) => resolve25({
11453
11582
  exitCode: code ?? 1,
11454
11583
  stdout: Buffer.concat(stdoutChunks).toString("utf8"),
11455
11584
  stderr: Buffer.concat(stderrChunks).toString("utf8")
@@ -11523,7 +11652,7 @@ async function runTaskRunPostValidationLifecycle(input) {
11523
11652
  config,
11524
11653
  sourceTask: input.sourceTask,
11525
11654
  uploadedSnapshot: input.uploadedSnapshot,
11526
- artifactRoot: resolve23(input.projectRoot, "artifacts", taskId3),
11655
+ artifactRoot: resolve24(input.projectRoot, "artifacts", taskId3),
11527
11656
  command: ghCommand,
11528
11657
  gitCommand,
11529
11658
  steerPi,
@@ -11653,7 +11782,7 @@ function summarizeValidationFailure(projectRoot, taskId3) {
11653
11782
  return null;
11654
11783
  }
11655
11784
  for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId3)) {
11656
- const summary = readJsonFile3(resolve23(artifactDir, "validation-summary.json"), null);
11785
+ const summary = readJsonFile3(resolve24(artifactDir, "validation-summary.json"), null);
11657
11786
  if (!summary || summary.status !== "fail") {
11658
11787
  continue;
11659
11788
  }
@@ -11734,9 +11863,9 @@ function readTaskRunAcceptedArtifactState(input) {
11734
11863
  if (!input.taskId || !input.workspaceDir) {
11735
11864
  return { accepted: false, reason: null };
11736
11865
  }
11737
- const artifactDir = resolve23(input.workspaceDir, "artifacts", input.taskId);
11738
- const reviewStatusPath = resolve23(artifactDir, "review-status.txt");
11739
- const taskResultPath = resolve23(artifactDir, "task-result.json");
11866
+ const artifactDir = resolve24(input.workspaceDir, "artifacts", input.taskId);
11867
+ const reviewStatusPath = resolve24(artifactDir, "review-status.txt");
11868
+ const taskResultPath = resolve24(artifactDir, "task-result.json");
11740
11869
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
11741
11870
  if (reviewStatus !== "APPROVED") {
11742
11871
  return { accepted: false, reason: null };
@@ -11773,12 +11902,12 @@ function resolveTaskRunRetryContext(input) {
11773
11902
  if (!input.taskId || !input.workspaceDir) {
11774
11903
  return { shouldRetry: false, failureDetail: null, nextPrompt: null };
11775
11904
  }
11776
- const artifactDir = resolve23(input.workspaceDir, "artifacts", input.taskId);
11777
- const reviewStatePath = resolve23(artifactDir, "review-state.json");
11778
- const reviewFeedbackPath = resolve23(artifactDir, "review-feedback.md");
11779
- const reviewStatusPath = resolve23(artifactDir, "review-status.txt");
11780
- const failedApproachesPath = resolve23(input.workspaceDir, ".rig", "state", "failed_approaches.md");
11781
- const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
11905
+ const artifactDir = resolve24(input.workspaceDir, "artifacts", input.taskId);
11906
+ const reviewStatePath = resolve24(artifactDir, "review-state.json");
11907
+ const reviewFeedbackPath = resolve24(artifactDir, "review-feedback.md");
11908
+ const reviewStatusPath = resolve24(artifactDir, "review-status.txt");
11909
+ const failedApproachesPath = resolve24(input.workspaceDir, ".rig", "state", "failed_approaches.md");
11910
+ const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
11782
11911
  const reviewState = readJsonFile3(reviewStatePath, null);
11783
11912
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
11784
11913
  const reviewRejected = isTaskRunReviewRejected(reviewState);
@@ -12188,15 +12317,15 @@ async function executeRigOwnedTaskRun(context, input) {
12188
12317
  const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
12189
12318
  const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
12190
12319
  const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
12191
- const planningArtifactPath = resolve23("artifacts", runtimeTaskId, "implementation-plan.md");
12320
+ const planningArtifactPath = resolve24("artifacts", runtimeTaskId, "implementation-plan.md");
12192
12321
  const persistedPlanning = {
12193
12322
  ...planningClassification,
12194
12323
  classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
12195
12324
  artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
12196
12325
  classifiedAt: new Date().toISOString()
12197
12326
  };
12198
- mkdirSync10(resolve23(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
12199
- writeFileSync7(resolve23(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
12327
+ mkdirSync11(resolve24(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
12328
+ writeFileSync8(resolve24(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
12200
12329
  `, "utf8");
12201
12330
  patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
12202
12331
  prompt = `${prompt}
@@ -12246,7 +12375,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12246
12375
  let verificationStarted = false;
12247
12376
  let reviewStarted = false;
12248
12377
  let latestRuntimeWorkspace = resumeMode && typeof existingRunRecord?.worktreePath === "string" ? existingRunRecord.worktreePath : null;
12249
- let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve23(existingRunRecord.sessionPath, "..") : null;
12378
+ let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve24(existingRunRecord.sessionPath, "..") : null;
12250
12379
  let latestLogsDir = resumeMode && typeof existingRunRecord?.logRoot === "string" ? existingRunRecord.logRoot : null;
12251
12380
  let latestProviderCommand = null;
12252
12381
  let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
@@ -12332,10 +12461,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12332
12461
  setRunStatusOrFail(context.projectRoot, input.runId, "running");
12333
12462
  patchAuthorityRun(context.projectRoot, input.runId, {
12334
12463
  worktreePath: latestRuntimeWorkspace,
12335
- artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve23(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
12464
+ artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve24(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
12336
12465
  logRoot: latestLogsDir,
12337
- sessionPath: latestSessionDir ? resolve23(latestSessionDir, "session.json") : null,
12338
- sessionLogPath: latestLogsDir ? resolve23(latestLogsDir, "agent-stdout.log") : null,
12466
+ sessionPath: latestSessionDir ? resolve24(latestSessionDir, "session.json") : null,
12467
+ sessionLogPath: latestLogsDir ? resolve24(latestLogsDir, "agent-stdout.log") : null,
12339
12468
  branch: runtimeId
12340
12469
  });
12341
12470
  if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
@@ -12343,8 +12472,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12343
12472
  const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
12344
12473
  const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
12345
12474
  if (readyFile) {
12346
- mkdirSync10(resolve23(readyFile, ".."), { recursive: true });
12347
- writeFileSync7(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
12475
+ mkdirSync11(resolve24(readyFile, ".."), { recursive: true });
12476
+ writeFileSync8(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
12348
12477
  `, "utf8");
12349
12478
  }
12350
12479
  appendRunLog(context.projectRoot, input.runId, {
@@ -12740,7 +12869,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12740
12869
  let acceptedArtifactObservedAt = null;
12741
12870
  let acceptedArtifactPollTimer = null;
12742
12871
  let acceptedArtifactKillTimer = null;
12743
- const attemptExit = await new Promise((resolve24) => {
12872
+ const attemptExit = await new Promise((resolve25) => {
12744
12873
  let settled = false;
12745
12874
  const settle = (result) => {
12746
12875
  if (settled)
@@ -12748,7 +12877,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12748
12877
  settled = true;
12749
12878
  if (acceptedArtifactPollTimer)
12750
12879
  clearInterval(acceptedArtifactPollTimer);
12751
- resolve24(result);
12880
+ resolve25(result);
12752
12881
  };
12753
12882
  const pollAcceptedArtifacts = () => {
12754
12883
  const artifactState = readTaskRunAcceptedArtifactState({
@@ -12951,7 +13080,7 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
12951
13080
  }
12952
13081
  if (planningClassification.planningRequired) {
12953
13082
  const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
12954
- const expectedPlanPath = resolve23(planWorkspace, planningArtifactPath);
13083
+ const expectedPlanPath = resolve24(planWorkspace, planningArtifactPath);
12955
13084
  if (!existsSync16(expectedPlanPath)) {
12956
13085
  const failedAt = new Date().toISOString();
12957
13086
  const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
@@ -13121,9 +13250,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
13121
13250
  });
13122
13251
  emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
13123
13252
  });
13124
- const exitCode = await new Promise((resolve24) => {
13125
- child.once("error", () => resolve24(1));
13126
- child.once("close", (code) => resolve24(code ?? 1));
13253
+ const exitCode = await new Promise((resolve25) => {
13254
+ child.once("error", () => resolve25(1));
13255
+ child.once("close", (code) => resolve25(code ?? 1));
13127
13256
  });
13128
13257
  for (const pendingLog of flushPendingClaudeToolUseLogs({
13129
13258
  runId: input.runId,
@@ -13264,8 +13393,8 @@ async function executeTest(context, args) {
13264
13393
  init_runner();
13265
13394
  init__parsers();
13266
13395
  init__paths();
13267
- import { existsSync as existsSync17, mkdirSync as mkdirSync11, readdirSync as readdirSync3, writeFileSync as writeFileSync8 } from "fs";
13268
- import { resolve as resolve24 } from "path";
13396
+ import { existsSync as existsSync17, mkdirSync as mkdirSync12, readdirSync as readdirSync3, writeFileSync as writeFileSync9 } from "fs";
13397
+ import { resolve as resolve25 } from "path";
13269
13398
  import { createPluginHost } from "@rig/core";
13270
13399
  import {
13271
13400
  isSupportedBunVersion as isSupportedBunVersion2,
@@ -13320,12 +13449,12 @@ function runSetupInit(projectRoot) {
13320
13449
  const stateDir = resolveControlPlaneHostStateDir(projectRoot);
13321
13450
  const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
13322
13451
  const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
13323
- mkdirSync11(stateDir, { recursive: true });
13324
- mkdirSync11(logsDir, { recursive: true });
13325
- mkdirSync11(artifactsDir, { recursive: true });
13326
- const failuresPath = resolve24(stateDir, "failed_approaches.md");
13452
+ mkdirSync12(stateDir, { recursive: true });
13453
+ mkdirSync12(logsDir, { recursive: true });
13454
+ mkdirSync12(artifactsDir, { recursive: true });
13455
+ const failuresPath = resolve25(stateDir, "failed_approaches.md");
13327
13456
  if (!existsSync17(failuresPath)) {
13328
- writeFileSync8(failuresPath, `# Failed Approaches
13457
+ writeFileSync9(failuresPath, `# Failed Approaches
13329
13458
 
13330
13459
  `, "utf-8");
13331
13460
  }
@@ -13342,17 +13471,17 @@ async function runSetupCheck(projectRoot, outputMode = "text") {
13342
13471
  }
13343
13472
  async function runSetupPreflight(projectRoot, outputMode = "text") {
13344
13473
  await runSetupCheck(projectRoot, outputMode);
13345
- const validationRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
13474
+ const validationRoot = resolve25(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
13346
13475
  if (existsSync17(validationRoot)) {
13347
13476
  const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
13348
13477
  for (const validator of validators) {
13349
- const script = resolve24(validationRoot, validator.name, "validate.sh");
13478
+ const script = resolve25(validationRoot, validator.name, "validate.sh");
13350
13479
  if (existsSync17(script)) {
13351
13480
  console.log(`OK: validator script ${script}`);
13352
13481
  }
13353
13482
  }
13354
13483
  }
13355
- const hooksRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
13484
+ const hooksRoot = resolve25(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
13356
13485
  if (existsSync17(hooksRoot)) {
13357
13486
  const hooks = readdirSync3(hooksRoot).filter((name) => name.endsWith(".sh"));
13358
13487
  for (const hook of hooks) {
@@ -13499,7 +13628,7 @@ var PROJECT_REQUIRED_GROUPS = new Set([
13499
13628
  ]);
13500
13629
  var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
13501
13630
  function hasInitializedRigProject(projectRoot) {
13502
- return RIG_CONFIG_FILENAMES.some((name) => existsSync19(resolve25(projectRoot, name))) || existsSync19(resolve25(projectRoot, ".rig"));
13631
+ return RIG_CONFIG_FILENAMES.some((name) => existsSync19(resolve26(projectRoot, name))) || existsSync19(resolve26(projectRoot, ".rig"));
13503
13632
  }
13504
13633
  function requireInitializedRigProject(context, group) {
13505
13634
  if (hasInitializedRigProject(context.projectRoot)) {
@@ -13553,7 +13682,7 @@ function resolveTopLevelLaunchState(context) {
13553
13682
  let selectedServer = null;
13554
13683
  if (projectInitialized) {
13555
13684
  try {
13556
- const statePath = resolve25(context.projectRoot, ".rig", "state", "connection.json");
13685
+ const statePath = resolve26(context.projectRoot, ".rig", "state", "connection.json");
13557
13686
  if (existsSync19(statePath)) {
13558
13687
  const parsed = JSON.parse(readFileSync13(statePath, "utf-8"));
13559
13688
  selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
@@ -13562,8 +13691,14 @@ function resolveTopLevelLaunchState(context) {
13562
13691
  }
13563
13692
  return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
13564
13693
  }
13694
+ function envTruthy(value) {
13695
+ if (!value)
13696
+ return false;
13697
+ const normalized = value.trim().toLowerCase();
13698
+ return normalized !== "0" && normalized !== "false" && normalized !== "no";
13699
+ }
13565
13700
  function shouldOpenApp(context) {
13566
- return context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
13701
+ return context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1" && process.env.RIG_PLAIN !== "1" && !envTruthy(process.env.CI);
13567
13702
  }
13568
13703
  async function openApp(context, options = {}) {
13569
13704
  const { runOperatorBoardLoop: runOperatorBoardLoop2 } = await Promise.resolve().then(() => (init_board(), exports_board));
@@ -13772,7 +13907,7 @@ var __testOnly = {
13772
13907
  };
13773
13908
  // packages/cli/src/launcher.ts
13774
13909
  import { existsSync as existsSync20 } from "fs";
13775
- import { basename as basename3, resolve as resolve26 } from "path";
13910
+ import { basename as basename3, resolve as resolve27 } from "path";
13776
13911
  import { loadDotEnvSecrets } from "@rig/runtime/baked-secrets";
13777
13912
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME, resolveNearestRigProjectRoot } from "@rig/runtime/layout";
13778
13913
 
@@ -13836,7 +13971,7 @@ function parsePolicyMode(value) {
13836
13971
  throw new Error(`Invalid --policy-mode value: ${value}. Use off|observe|enforce.`);
13837
13972
  }
13838
13973
  function hasRigProjectMarker(candidate) {
13839
- return existsSync20(resolve26(candidate, RIG_DEFINITION_DIRNAME)) || existsSync20(resolve26(candidate, RIG_STATE_DIRNAME)) || existsSync20(resolve26(candidate, "rig.config.ts")) || existsSync20(resolve26(candidate, "rig.config.json")) || existsSync20(resolve26(candidate, ".git"));
13974
+ return existsSync20(resolve27(candidate, RIG_DEFINITION_DIRNAME)) || existsSync20(resolve27(candidate, RIG_STATE_DIRNAME)) || existsSync20(resolve27(candidate, "rig.config.ts")) || existsSync20(resolve27(candidate, "rig.config.json")) || existsSync20(resolve27(candidate, ".git"));
13840
13975
  }
13841
13976
  function resolveProjectRoot({
13842
13977
  envProjectRoot,
@@ -13845,19 +13980,19 @@ function resolveProjectRoot({
13845
13980
  cwd = process.cwd()
13846
13981
  }) {
13847
13982
  if (envProjectRoot) {
13848
- return resolve26(cwd, envProjectRoot);
13983
+ return resolve27(cwd, envProjectRoot);
13849
13984
  }
13850
13985
  const fallbackImportDir = importDir ?? cwd;
13851
13986
  const execName = basename3(execPath).toLowerCase();
13852
- const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve26(execPath, "..", "..")] : [];
13853
- const candidates = [cwd, ...execCandidates, resolve26(fallbackImportDir, "..")];
13987
+ const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve27(execPath, "..", "..")] : [];
13988
+ const candidates = [cwd, ...execCandidates, resolve27(fallbackImportDir, "..")];
13854
13989
  for (const candidate of candidates) {
13855
13990
  const nearest = resolveNearestRigProjectRoot(candidate);
13856
13991
  if (hasRigProjectMarker(nearest)) {
13857
13992
  return nearest;
13858
13993
  }
13859
13994
  }
13860
- return resolve26(cwd);
13995
+ return resolve27(cwd);
13861
13996
  }
13862
13997
  function normalizeCliErrorCode(message2, isCliError) {
13863
13998
  if (message2.startsWith("Invalid --policy-mode value:")) {
@@ -13931,7 +14066,7 @@ async function runRigCli(module, options = {}) {
13931
14066
  runId: context.runId,
13932
14067
  outcome,
13933
14068
  eventsFile: context.eventBus.getEventsFile(),
13934
- policyFile: resolve26(projectRoot, "rig", "policy", "policy.json"),
14069
+ policyFile: resolve27(projectRoot, "rig", "policy", "policy.json"),
13935
14070
  policyMode: context.policyMode ?? policyMode ?? module.loadPolicy(projectRoot).mode
13936
14071
  }, null, 2));
13937
14072
  }