@h-rig/cli 0.0.6-alpha.81 → 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 +2807 -1443
  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 +102 -36
  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 +13776 -12369
  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 +3806 -2878
  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 +15 -13
  33. package/dist/src/app-opentui/registry.js +3228 -2396
  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 +413 -958
  39. package/dist/src/app-opentui/render/image-visual-layer.d.ts +19 -10
  40. package/dist/src/app-opentui/render/image-visual-layer.js +391 -357
  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 +2329 -1512
  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 -1480
@@ -916,17 +916,21 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
916
916
  const scopedKey = resolve10(projectRoot ?? process.cwd());
917
917
  scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
918
918
  }
919
- function readPrivateRemoteSessionToken(projectRoot) {
919
+ function readRemoteAuthState(projectRoot) {
920
920
  const path = resolve10(projectRoot, ".rig", "state", "github-auth.json");
921
921
  if (!existsSync6(path))
922
922
  return null;
923
923
  try {
924
924
  const parsed = JSON.parse(readFileSync4(path, "utf8"));
925
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
925
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
926
926
  } catch {
927
927
  return null;
928
928
  }
929
929
  }
930
+ function readPrivateRemoteSessionToken(projectRoot) {
931
+ const parsed = readRemoteAuthState(projectRoot);
932
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
933
+ }
930
934
  function readGitHubBearerTokenForRemote(projectRoot) {
931
935
  const scopedKey = resolve10(projectRoot);
932
936
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -937,15 +941,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
937
941
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
938
942
  }
939
943
  function readStoredGitHubAuthToken(projectRoot) {
940
- const path = resolve10(projectRoot, ".rig", "state", "github-auth.json");
941
- if (!existsSync6(path))
944
+ const parsed = readRemoteAuthState(projectRoot);
945
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
946
+ }
947
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
948
+ const repo = readRepoConnection(projectRoot);
949
+ const slug = repo?.project?.trim();
950
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
942
951
  return null;
943
- try {
944
- const parsed = JSON.parse(readFileSync4(path, "utf8"));
945
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
946
- } catch {
952
+ const auth = readRemoteAuthState(projectRoot);
953
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
954
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
955
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
947
956
  return null;
948
- }
957
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
958
+ if (!checkoutBaseDir)
959
+ return null;
960
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
961
+ writeRepoServerProjectRoot(projectRoot, inferred);
962
+ return inferred;
949
963
  }
950
964
  function readLocalConnectionFallbackToken(projectRoot) {
951
965
  return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
@@ -956,7 +970,7 @@ async function ensureServerForCli(projectRoot) {
956
970
  if (selected?.connection.kind === "remote") {
957
971
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
958
972
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
959
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
973
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
960
974
  return {
961
975
  baseUrl: selected.connection.baseUrl,
962
976
  authToken,
@@ -985,7 +999,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
985
999
  if (!slug)
986
1000
  return null;
987
1001
  try {
988
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
1002
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
1003
+ if (authToken && queryAuthFallbackEnabled())
1004
+ url.searchParams.set("rt", authToken);
1005
+ const response = await fetch(url, {
989
1006
  headers: mergeHeaders(undefined, authToken)
990
1007
  });
991
1008
  if (!response.ok)
@@ -1012,10 +1029,23 @@ function appendTaskFilterParams(url, filters) {
1012
1029
  if (filters.limit !== undefined)
1013
1030
  url.searchParams.set("limit", String(filters.limit));
1014
1031
  }
1032
+ function mergeCookie(existing, name, value) {
1033
+ const encoded = `${name}=${encodeURIComponent(value)}`;
1034
+ if (!existing?.trim())
1035
+ return encoded;
1036
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
1037
+ return [...parts, encoded].join("; ");
1038
+ }
1039
+ function queryAuthFallbackEnabled(env = process.env) {
1040
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
1041
+ }
1015
1042
  function mergeHeaders(headers, authToken) {
1016
1043
  const merged = new Headers(headers);
1017
1044
  if (authToken) {
1018
- merged.set("authorization", `Bearer ${authToken}`);
1045
+ const bearer = `Bearer ${authToken}`;
1046
+ merged.set("authorization", bearer);
1047
+ merged.set("x-auth", bearer);
1048
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
1019
1049
  }
1020
1050
  return merged;
1021
1051
  }
@@ -1075,15 +1105,34 @@ async function buildServerFailureContext(projectRoot, server) {
1075
1105
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
1076
1106
  };
1077
1107
  }
1108
+ function isLoopbackRemoteBaseUrl(baseUrl) {
1109
+ try {
1110
+ const host = new URL(baseUrl).hostname.toLowerCase();
1111
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
1112
+ } catch {
1113
+ return false;
1114
+ }
1115
+ }
1116
+ function canUseRemoteWithoutProjectRoot(pathname) {
1117
+ 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/");
1118
+ }
1078
1119
  async function requestServerJson(context, pathname, init = {}) {
1079
1120
  const server = await ensureServerForCli(context.projectRoot);
1121
+ const requestUrl = new URL(`${server.baseUrl}${pathname}`);
1122
+ if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
1123
+ const repo = readRepoConnection(context.projectRoot);
1124
+ 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." });
1125
+ }
1080
1126
  const headers = mergeHeaders(init.headers, server.authToken);
1081
1127
  if (server.serverProjectRoot)
1082
1128
  headers.set("x-rig-project-root", server.serverProjectRoot);
1129
+ if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
1130
+ requestUrl.searchParams.set("rt", server.authToken);
1131
+ }
1083
1132
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
1084
1133
  let response;
1085
1134
  try {
1086
- response = await fetch(`${server.baseUrl}${pathname}`, {
1135
+ response = await fetch(requestUrl, {
1087
1136
  ...init,
1088
1137
  headers
1089
1138
  });
@@ -1145,11 +1194,26 @@ async function getGitHubAuthStatusViaServer(context) {
1145
1194
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
1146
1195
  }
1147
1196
  async function postGitHubTokenViaServer(context, token, options = {}) {
1148
- const payload = await requestServerJson(context, "/api/github/auth/token", {
1149
- method: "POST",
1150
- headers: { "content-type": "application/json" },
1151
- body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot })
1152
- });
1197
+ const server = await ensureServerForCli(context.projectRoot);
1198
+ const requestUrl = new URL(`${server.baseUrl}/api/github/auth/token`);
1199
+ reportServerPhase("POST /api/github/auth/token\u2026");
1200
+ let response;
1201
+ try {
1202
+ response = await fetch(requestUrl, {
1203
+ method: "POST",
1204
+ headers: { "content-type": "application/json" },
1205
+ body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
1206
+ });
1207
+ } catch (error) {
1208
+ const failure = await buildServerFailureContext(context.projectRoot, server);
1209
+ throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
1210
+ ${failure.contextLine}`, 1, { hint: failure.hint });
1211
+ }
1212
+ const payload = await response.json().catch(() => null);
1213
+ if (!response.ok) {
1214
+ const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
1215
+ 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`." });
1216
+ }
1153
1217
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
1154
1218
  }
1155
1219
  async function prepareRemoteCheckoutViaServer(context, input) {
@@ -1480,7 +1544,8 @@ async function runFastTaskRunPreflight(context, options = {}) {
1480
1544
  }
1481
1545
  }
1482
1546
  const repo = readRepoConnection(context.projectRoot);
1483
- 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>`."));
1547
+ const remoteWithoutProjectLink = selectedServer?.connectionKind === "remote" && !repo?.project;
1548
+ 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>`."));
1484
1549
  try {
1485
1550
  const auth = await request("/api/github/auth/status");
1486
1551
  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>`."));
@@ -2524,7 +2589,7 @@ var init__operator_surface = __esm(() => {
2524
2589
  });
2525
2590
 
2526
2591
  // packages/cli/src/commands/_pi-frontend.ts
2527
- import { existsSync as existsSync14, mkdirSync as mkdirSync8, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
2592
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync5, writeFileSync as writeFileSync7 } from "fs";
2528
2593
  import { homedir as homedir6, tmpdir } from "os";
2529
2594
  import { join as join3 } from "path";
2530
2595
  import { main as runPiMain } from "@earendil-works/pi-coding-agent";
@@ -2559,7 +2624,7 @@ function buildOperatorPiEnv(input) {
2559
2624
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
2560
2625
  const server = await ensureServerForCli(context.projectRoot);
2561
2626
  const localCwd = join3(homedir6(), ".rig", "drones", runId.slice(0, 8));
2562
- mkdirSync8(localCwd, { recursive: true });
2627
+ mkdirSync9(localCwd, { recursive: true });
2563
2628
  trustDroneCwd(localCwd);
2564
2629
  installRigPiTheme();
2565
2630
  let sessionFileArg = [];
@@ -2581,7 +2646,7 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
2581
2646
  return line;
2582
2647
  }).join(`
2583
2648
  `);
2584
- writeFileSync6(localSessionPath, content);
2649
+ writeFileSync7(localSessionPath, content);
2585
2650
  sessionFileArg = ["--session", localSessionPath];
2586
2651
  }
2587
2652
  } catch {}
@@ -2590,12 +2655,12 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
2590
2655
  function trustDroneCwd(localCwd) {
2591
2656
  try {
2592
2657
  const agentDir = join3(homedir6(), ".pi", "agent");
2593
- mkdirSync8(agentDir, { recursive: true });
2658
+ mkdirSync9(agentDir, { recursive: true });
2594
2659
  const trustPath = join3(agentDir, "trust.json");
2595
2660
  const store = existsSync14(trustPath) ? JSON.parse(readFileSync10(trustPath, "utf8")) : {};
2596
2661
  if (store[localCwd] !== true) {
2597
2662
  store[localCwd] = true;
2598
- writeFileSync6(trustPath, `${JSON.stringify(store, null, "\t")}
2663
+ writeFileSync7(trustPath, `${JSON.stringify(store, null, "\t")}
2599
2664
  `);
2600
2665
  }
2601
2666
  } catch {}
@@ -2603,12 +2668,12 @@ function trustDroneCwd(localCwd) {
2603
2668
  function installRigPiTheme() {
2604
2669
  try {
2605
2670
  const themesDir = join3(homedir6(), ".pi", "agent", "themes");
2606
- mkdirSync8(themesDir, { recursive: true });
2671
+ mkdirSync9(themesDir, { recursive: true });
2607
2672
  const themePath = join3(themesDir, "rig.json");
2608
2673
  const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
2609
2674
  `;
2610
2675
  if (!existsSync14(themePath) || readFileSync10(themePath, "utf8") !== next) {
2611
- writeFileSync6(themePath, next);
2676
+ writeFileSync7(themePath, next);
2612
2677
  }
2613
2678
  } catch {}
2614
2679
  }
@@ -2628,6 +2693,7 @@ async function attachRunBundledPiFrontend(context, input) {
2628
2693
  let detached = false;
2629
2694
  try {
2630
2695
  await runPiMain([
2696
+ "--offline",
2631
2697
  "--no-extensions",
2632
2698
  "--no-skills",
2633
2699
  "--no-prompt-templates",
@@ -3298,7 +3364,7 @@ var init__task_picker = __esm(() => {
3298
3364
  // packages/cli/src/commands/task.ts
3299
3365
  import { readFileSync as readFileSync11 } from "fs";
3300
3366
  import { spawnSync as spawnSync3 } from "child_process";
3301
- import { resolve as resolve21 } from "path";
3367
+ import { resolve as resolve22 } from "path";
3302
3368
  import {
3303
3369
  taskArtifactDir,
3304
3370
  taskArtifacts,
@@ -3576,7 +3642,7 @@ async function executeTask(context, args, options) {
3576
3642
  const fileFlag = takeOption(rest.slice(1), "--file");
3577
3643
  let content;
3578
3644
  if (fileFlag.value) {
3579
- content = readFileSync11(resolve21(context.projectRoot, fileFlag.value), "utf-8");
3645
+ content = readFileSync11(resolve22(context.projectRoot, fileFlag.value), "utf-8");
3580
3646
  } else {
3581
3647
  content = await readStdin();
3582
3648
  }
@@ -4657,11 +4723,11 @@ async function runOperatorBoard(context, options = {}) {
4657
4723
  }, BOARD_REFRESH_MS);
4658
4724
  tui.start();
4659
4725
  refresh({ quiet: true });
4660
- await new Promise((resolve24) => {
4726
+ await new Promise((resolve25) => {
4661
4727
  const poll = setInterval(() => {
4662
4728
  if (stopped) {
4663
4729
  clearInterval(poll);
4664
- resolve24();
4730
+ resolve25();
4665
4731
  }
4666
4732
  }, 50);
4667
4733
  });
@@ -4695,7 +4761,7 @@ import {
4695
4761
  existsSync as existsSync18,
4696
4762
  readFileSync as readFileSync13
4697
4763
  } from "fs";
4698
- import { resolve as resolve24 } from "path";
4764
+ import { resolve as resolve25 } from "path";
4699
4765
  import { readBuildConfig } from "@rig/runtime/build-time-config";
4700
4766
 
4701
4767
  // packages/cli/src/commands/browser.ts
@@ -8923,14 +8989,64 @@ Usage: rig init`, 1);
8923
8989
  // packages/cli/src/commands/github.ts
8924
8990
  init_runner();
8925
8991
  init__server_client();
8992
+ init__connection_state();
8926
8993
  init__async_ui();
8927
8994
  import { spawnSync as spawnSync2 } from "child_process";
8995
+ import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync6 } from "fs";
8996
+ import { dirname as dirname4, resolve as resolve18 } from "path";
8928
8997
  function printPayload(context, payload, fallback) {
8929
8998
  if (context.outputMode === "json")
8930
8999
  console.log(JSON.stringify(payload, null, 2));
8931
9000
  else
8932
9001
  console.log(fallback);
8933
9002
  }
9003
+ function apiSessionTokenFrom2(payload) {
9004
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
9005
+ return null;
9006
+ const token = payload.apiSessionToken;
9007
+ return typeof token === "string" && token.trim() ? token.trim() : null;
9008
+ }
9009
+ function payloadString(payload, key) {
9010
+ const value = payload[key];
9011
+ return typeof value === "string" && value.trim() ? value.trim() : null;
9012
+ }
9013
+ function payloadRecord(payload, key) {
9014
+ const value = payload[key];
9015
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
9016
+ }
9017
+ function remoteNamespaceMetadata(result) {
9018
+ const namespace = payloadRecord(result, "userNamespace");
9019
+ return {
9020
+ ...payloadString(result, "login") ? { login: payloadString(result, "login") } : {},
9021
+ ...payloadString(result, "userId") ? { userId: payloadString(result, "userId") } : {},
9022
+ ...namespace && payloadString(namespace, "key") ? { userNamespaceKey: payloadString(namespace, "key") } : {},
9023
+ ...namespace && payloadString(namespace, "root") ? { userNamespaceRoot: payloadString(namespace, "root") } : {},
9024
+ ...namespace && payloadString(namespace, "checkoutBaseDir") ? { checkoutBaseDir: payloadString(namespace, "checkoutBaseDir") } : {},
9025
+ ...namespace && payloadString(namespace, "snapshotBaseDir") ? { snapshotBaseDir: payloadString(namespace, "snapshotBaseDir") } : {}
9026
+ };
9027
+ }
9028
+ function persistRemoteAuthSession(context, source, result, fallbackToken) {
9029
+ const apiSessionToken = apiSessionTokenFrom2(result);
9030
+ setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? fallbackToken, context.projectRoot);
9031
+ if (!apiSessionToken)
9032
+ return;
9033
+ const repo = readRepoConnection(context.projectRoot);
9034
+ const path = resolve18(context.projectRoot, ".rig", "state", "github-auth.json");
9035
+ mkdirSync8(dirname4(path), { recursive: true });
9036
+ writeFileSync6(path, `${JSON.stringify({
9037
+ authenticated: true,
9038
+ source,
9039
+ storedOnServer: true,
9040
+ ...repo?.project ? { selectedRepo: repo.project } : {},
9041
+ ...remoteNamespaceMetadata(result),
9042
+ apiSessionToken,
9043
+ updatedAt: new Date().toISOString()
9044
+ }, null, 2)}
9045
+ `, "utf8");
9046
+ }
9047
+ function isSignedIn(status) {
9048
+ return status.signedIn === true || status.authenticated === true;
9049
+ }
8934
9050
  function readGhToken() {
8935
9051
  const result = spawnSync2("gh", ["auth", "token"], { encoding: "utf8" });
8936
9052
  if (result.status !== 0) {
@@ -8952,7 +9068,7 @@ async function executeGithub(context, args) {
8952
9068
  if (rest.length > 0)
8953
9069
  throw new CliError("Usage: rig github auth status", 1);
8954
9070
  const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
8955
- printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
9071
+ printPayload(context, status, `GitHub auth: ${isSignedIn(status) ? "authenticated" : "unauthenticated"}`);
8956
9072
  return { ok: true, group: "github", command: "auth status", details: status };
8957
9073
  }
8958
9074
  case "token": {
@@ -8962,16 +9078,20 @@ async function executeGithub(context, args) {
8962
9078
  const token = parsed.value?.trim();
8963
9079
  if (!token)
8964
9080
  throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
8965
- const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
8966
- printPayload(context, result, "GitHub token stored on the selected Rig server.");
9081
+ const repo = readRepoConnection(context.projectRoot);
9082
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token, repo?.project ? { selectedRepo: repo.project } : {}), { outputMode: context.outputMode });
9083
+ persistRemoteAuthSession(context, "token", result, token);
9084
+ printPayload(context, result, "GitHub token stored on the selected server.");
8967
9085
  return { ok: true, group: "github", command: "auth token", details: result };
8968
9086
  }
8969
9087
  case "import-gh": {
8970
9088
  if (rest.length > 0)
8971
9089
  throw new CliError("Usage: rig github auth import-gh", 1);
8972
9090
  const importedToken = readGhToken();
8973
- const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
8974
- printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
9091
+ const repo = readRepoConnection(context.projectRoot);
9092
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken, repo?.project ? { selectedRepo: repo.project } : {}), { outputMode: context.outputMode });
9093
+ persistRemoteAuthSession(context, "gh", result, importedToken);
9094
+ printPayload(context, result, "GitHub token imported from gh and stored on the selected server.");
8975
9095
  return { ok: true, group: "github", command: "auth import-gh", details: result };
8976
9096
  }
8977
9097
  default:
@@ -9001,7 +9121,7 @@ init_runner();
9001
9121
  init__authority_runs();
9002
9122
  init__paths();
9003
9123
  import { readFileSync as readFileSync8 } from "fs";
9004
- import { resolve as resolve18 } from "path";
9124
+ import { resolve as resolve19 } from "path";
9005
9125
  import {
9006
9126
  appendRunJournalEvent,
9007
9127
  appendRunLogEntry,
@@ -9038,7 +9158,7 @@ function touchAuthorityRun(projectRoot, runId) {
9038
9158
  if (!current) {
9039
9159
  return;
9040
9160
  }
9041
- writeJsonFile3(resolve18(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
9161
+ writeJsonFile3(resolve19(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
9042
9162
  ...current,
9043
9163
  updatedAt: new Date().toISOString()
9044
9164
  });
@@ -9276,7 +9396,7 @@ init_runner();
9276
9396
  init__server_client();
9277
9397
  init__async_ui();
9278
9398
  import { existsSync as existsSync12, readFileSync as readFileSync9 } from "fs";
9279
- import { resolve as resolve19 } from "path";
9399
+ import { resolve as resolve20 } from "path";
9280
9400
  import {
9281
9401
  listAuthorityRuns,
9282
9402
  readAuthorityRun as readAuthorityRun3,
@@ -9320,7 +9440,7 @@ async function executeInspect(context, args) {
9320
9440
  }
9321
9441
  return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: fallback.runId, source: "server", entries } };
9322
9442
  }
9323
- const logsPath = resolve19(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
9443
+ const logsPath = resolve20(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
9324
9444
  if (!existsSync12(logsPath)) {
9325
9445
  throw new CliError(`No logs found for run ${latestRun.runId}.`, 1, { hint: `Try \`rig run show ${latestRun.runId}\` or \`rig run replay ${latestRun.runId}\`.` });
9326
9446
  }
@@ -9408,7 +9528,7 @@ async function executeInspect(context, args) {
9408
9528
  return { ok: true, group: "inspect", command };
9409
9529
  case "audit": {
9410
9530
  requireNoExtraArgs(rest, "rig inspect audit");
9411
- const auditPath = resolve19(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
9531
+ const auditPath = resolve20(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
9412
9532
  if (!existsSync12(auditPath)) {
9413
9533
  console.log("No audit log found.");
9414
9534
  } else {
@@ -10067,7 +10187,7 @@ import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/co
10067
10187
 
10068
10188
  // packages/cli/src/commands/_run-replay.ts
10069
10189
  import { existsSync as existsSync13, readdirSync as readdirSync2 } from "fs";
10070
- import { join as join2, resolve as resolve20 } from "path";
10190
+ import { join as join2, resolve as resolve21 } from "path";
10071
10191
  import {
10072
10192
  readAuthorityRun as readAuthorityRun4,
10073
10193
  readJsonlFile as readJsonlFile3,
@@ -10160,7 +10280,7 @@ function resolveRunSessionFile(record) {
10160
10280
  const sessionId = text(piSession.sessionId);
10161
10281
  if (!cwd || !sessionId)
10162
10282
  return null;
10163
- const sessionDir = resolve20(cwd, ".rig", "session");
10283
+ const sessionDir = resolve21(cwd, ".rig", "session");
10164
10284
  try {
10165
10285
  const match = readdirSync2(sessionDir).find((name) => name.endsWith(`_${sessionId}.jsonl`));
10166
10286
  return match ? join2(sessionDir, match) : null;
@@ -10658,6 +10778,9 @@ async function executeRun(context, args) {
10658
10778
  console.log(`Stop requested: ${runId}`);
10659
10779
  return { ok: true, group: "run", command, details: stopped };
10660
10780
  }
10781
+ if (isRemoteConnectionSelected(context.projectRoot)) {
10782
+ throw new CliError("Remote run stop requires an explicit run id.", 2, { hint: "Run `rig run list`, then `rig run stop <run-id>`." });
10783
+ }
10661
10784
  const result = await runStop(context.projectRoot);
10662
10785
  if (result.remaining.length > 0) {
10663
10786
  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." });
@@ -10774,7 +10897,13 @@ async function executeConnectionCommand(context, args, options) {
10774
10897
  if (!state.connections[alias])
10775
10898
  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>`." });
10776
10899
  }
10777
- const repoState = { selected: alias, linkedAt: new Date().toISOString() };
10900
+ const previousRepo = readRepoConnection(context.projectRoot);
10901
+ const repoState = {
10902
+ selected: alias,
10903
+ ...previousRepo?.project ? { project: previousRepo.project } : {},
10904
+ linkedAt: new Date().toISOString(),
10905
+ ...previousRepo?.serverProjectRoot && previousRepo.selected === alias ? { serverProjectRoot: previousRepo.serverProjectRoot } : {}
10906
+ };
10778
10907
  writeRepoConnection(context.projectRoot, repoState);
10779
10908
  printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
10780
10909
  ["selected", alias],
@@ -11009,8 +11138,8 @@ init_task();
11009
11138
 
11010
11139
  // packages/cli/src/commands/task-run-driver.ts
11011
11140
  init_runner();
11012
- import { copyFileSync as copyFileSync3, existsSync as existsSync15, mkdirSync as mkdirSync9, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
11013
- import { resolve as resolve22 } from "path";
11141
+ import { copyFileSync as copyFileSync3, existsSync as existsSync15, mkdirSync as mkdirSync10, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync8 } from "fs";
11142
+ import { resolve as resolve23 } from "path";
11014
11143
  import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
11015
11144
  import { createInterface as createLineInterface } from "readline";
11016
11145
  import { loadConfig as loadConfig2 } from "@rig/core/load-config";
@@ -11109,12 +11238,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
11109
11238
  return 0;
11110
11239
  let copied = 0;
11111
11240
  for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
11112
- const sourcePath = resolve22(sourceRoot, relativePath);
11113
- const targetPath = resolve22(targetRoot, relativePath);
11241
+ const sourcePath = resolve23(sourceRoot, relativePath);
11242
+ const targetPath = resolve23(targetRoot, relativePath);
11114
11243
  try {
11115
11244
  if (!statSync2(sourcePath).isFile())
11116
11245
  continue;
11117
- mkdirSync9(resolve22(targetPath, ".."), { recursive: true });
11246
+ mkdirSync10(resolve23(targetPath, ".."), { recursive: true });
11118
11247
  copyFileSync3(sourcePath, targetPath);
11119
11248
  copied += 1;
11120
11249
  } catch {}
@@ -11153,7 +11282,7 @@ function buildDirtyBaselineHandshakeEnv(input) {
11153
11282
  return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
11154
11283
  return {
11155
11284
  RIG_BASELINE_MODE: "dirty-snapshot",
11156
- RIG_DIRTY_BASELINE_READY_FILE: resolve22(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
11285
+ RIG_DIRTY_BASELINE_READY_FILE: resolve23(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
11157
11286
  };
11158
11287
  }
11159
11288
  function positiveInt(value, fallback) {
@@ -11258,9 +11387,9 @@ function createCommandRunner(binary) {
11258
11387
  const stderrChunks = [];
11259
11388
  child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
11260
11389
  child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
11261
- return await new Promise((resolve23) => {
11262
- child.once("error", (error) => resolve23({ exitCode: 1, stderr: error.message }));
11263
- child.once("close", (code) => resolve23({
11390
+ return await new Promise((resolve24) => {
11391
+ child.once("error", (error) => resolve24({ exitCode: 1, stderr: error.message }));
11392
+ child.once("close", (code) => resolve24({
11264
11393
  exitCode: code ?? 1,
11265
11394
  stdout: Buffer.concat(stdoutChunks).toString("utf8"),
11266
11395
  stderr: Buffer.concat(stderrChunks).toString("utf8")
@@ -11334,7 +11463,7 @@ async function runTaskRunPostValidationLifecycle(input) {
11334
11463
  config,
11335
11464
  sourceTask: input.sourceTask,
11336
11465
  uploadedSnapshot: input.uploadedSnapshot,
11337
- artifactRoot: resolve22(input.projectRoot, "artifacts", taskId3),
11466
+ artifactRoot: resolve23(input.projectRoot, "artifacts", taskId3),
11338
11467
  command: ghCommand,
11339
11468
  gitCommand,
11340
11469
  steerPi,
@@ -11464,7 +11593,7 @@ function summarizeValidationFailure(projectRoot, taskId3) {
11464
11593
  return null;
11465
11594
  }
11466
11595
  for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId3)) {
11467
- const summary = readJsonFile3(resolve22(artifactDir, "validation-summary.json"), null);
11596
+ const summary = readJsonFile3(resolve23(artifactDir, "validation-summary.json"), null);
11468
11597
  if (!summary || summary.status !== "fail") {
11469
11598
  continue;
11470
11599
  }
@@ -11545,9 +11674,9 @@ function readTaskRunAcceptedArtifactState(input) {
11545
11674
  if (!input.taskId || !input.workspaceDir) {
11546
11675
  return { accepted: false, reason: null };
11547
11676
  }
11548
- const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
11549
- const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
11550
- const taskResultPath = resolve22(artifactDir, "task-result.json");
11677
+ const artifactDir = resolve23(input.workspaceDir, "artifacts", input.taskId);
11678
+ const reviewStatusPath = resolve23(artifactDir, "review-status.txt");
11679
+ const taskResultPath = resolve23(artifactDir, "task-result.json");
11551
11680
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
11552
11681
  if (reviewStatus !== "APPROVED") {
11553
11682
  return { accepted: false, reason: null };
@@ -11584,12 +11713,12 @@ function resolveTaskRunRetryContext(input) {
11584
11713
  if (!input.taskId || !input.workspaceDir) {
11585
11714
  return { shouldRetry: false, failureDetail: null, nextPrompt: null };
11586
11715
  }
11587
- const artifactDir = resolve22(input.workspaceDir, "artifacts", input.taskId);
11588
- const reviewStatePath = resolve22(artifactDir, "review-state.json");
11589
- const reviewFeedbackPath = resolve22(artifactDir, "review-feedback.md");
11590
- const reviewStatusPath = resolve22(artifactDir, "review-status.txt");
11591
- const failedApproachesPath = resolve22(input.workspaceDir, ".rig", "state", "failed_approaches.md");
11592
- const validationSummaryPath = resolve22(artifactDir, "validation-summary.json");
11716
+ const artifactDir = resolve23(input.workspaceDir, "artifacts", input.taskId);
11717
+ const reviewStatePath = resolve23(artifactDir, "review-state.json");
11718
+ const reviewFeedbackPath = resolve23(artifactDir, "review-feedback.md");
11719
+ const reviewStatusPath = resolve23(artifactDir, "review-status.txt");
11720
+ const failedApproachesPath = resolve23(input.workspaceDir, ".rig", "state", "failed_approaches.md");
11721
+ const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
11593
11722
  const reviewState = readJsonFile3(reviewStatePath, null);
11594
11723
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
11595
11724
  const reviewRejected = isTaskRunReviewRejected(reviewState);
@@ -11999,15 +12128,15 @@ async function executeRigOwnedTaskRun(context, input) {
11999
12128
  const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
12000
12129
  const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
12001
12130
  const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
12002
- const planningArtifactPath = resolve22("artifacts", runtimeTaskId, "implementation-plan.md");
12131
+ const planningArtifactPath = resolve23("artifacts", runtimeTaskId, "implementation-plan.md");
12003
12132
  const persistedPlanning = {
12004
12133
  ...planningClassification,
12005
12134
  classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
12006
12135
  artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
12007
12136
  classifiedAt: new Date().toISOString()
12008
12137
  };
12009
- mkdirSync9(resolve22(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
12010
- writeFileSync7(resolve22(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
12138
+ mkdirSync10(resolve23(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
12139
+ writeFileSync8(resolve23(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
12011
12140
  `, "utf8");
12012
12141
  patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
12013
12142
  prompt = `${prompt}
@@ -12057,7 +12186,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12057
12186
  let verificationStarted = false;
12058
12187
  let reviewStarted = false;
12059
12188
  let latestRuntimeWorkspace = resumeMode && typeof existingRunRecord?.worktreePath === "string" ? existingRunRecord.worktreePath : null;
12060
- let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve22(existingRunRecord.sessionPath, "..") : null;
12189
+ let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve23(existingRunRecord.sessionPath, "..") : null;
12061
12190
  let latestLogsDir = resumeMode && typeof existingRunRecord?.logRoot === "string" ? existingRunRecord.logRoot : null;
12062
12191
  let latestProviderCommand = null;
12063
12192
  let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
@@ -12143,10 +12272,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12143
12272
  setRunStatusOrFail(context.projectRoot, input.runId, "running");
12144
12273
  patchAuthorityRun(context.projectRoot, input.runId, {
12145
12274
  worktreePath: latestRuntimeWorkspace,
12146
- artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve22(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
12275
+ artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve23(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
12147
12276
  logRoot: latestLogsDir,
12148
- sessionPath: latestSessionDir ? resolve22(latestSessionDir, "session.json") : null,
12149
- sessionLogPath: latestLogsDir ? resolve22(latestLogsDir, "agent-stdout.log") : null,
12277
+ sessionPath: latestSessionDir ? resolve23(latestSessionDir, "session.json") : null,
12278
+ sessionLogPath: latestLogsDir ? resolve23(latestLogsDir, "agent-stdout.log") : null,
12150
12279
  branch: runtimeId
12151
12280
  });
12152
12281
  if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
@@ -12154,8 +12283,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12154
12283
  const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
12155
12284
  const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
12156
12285
  if (readyFile) {
12157
- mkdirSync9(resolve22(readyFile, ".."), { recursive: true });
12158
- writeFileSync7(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
12286
+ mkdirSync10(resolve23(readyFile, ".."), { recursive: true });
12287
+ writeFileSync8(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
12159
12288
  `, "utf8");
12160
12289
  }
12161
12290
  appendRunLog(context.projectRoot, input.runId, {
@@ -12551,7 +12680,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12551
12680
  let acceptedArtifactObservedAt = null;
12552
12681
  let acceptedArtifactPollTimer = null;
12553
12682
  let acceptedArtifactKillTimer = null;
12554
- const attemptExit = await new Promise((resolve23) => {
12683
+ const attemptExit = await new Promise((resolve24) => {
12555
12684
  let settled = false;
12556
12685
  const settle = (result) => {
12557
12686
  if (settled)
@@ -12559,7 +12688,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
12559
12688
  settled = true;
12560
12689
  if (acceptedArtifactPollTimer)
12561
12690
  clearInterval(acceptedArtifactPollTimer);
12562
- resolve23(result);
12691
+ resolve24(result);
12563
12692
  };
12564
12693
  const pollAcceptedArtifacts = () => {
12565
12694
  const artifactState = readTaskRunAcceptedArtifactState({
@@ -12762,7 +12891,7 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
12762
12891
  }
12763
12892
  if (planningClassification.planningRequired) {
12764
12893
  const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
12765
- const expectedPlanPath = resolve22(planWorkspace, planningArtifactPath);
12894
+ const expectedPlanPath = resolve23(planWorkspace, planningArtifactPath);
12766
12895
  if (!existsSync15(expectedPlanPath)) {
12767
12896
  const failedAt = new Date().toISOString();
12768
12897
  const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
@@ -12932,9 +13061,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
12932
13061
  });
12933
13062
  emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
12934
13063
  });
12935
- const exitCode = await new Promise((resolve23) => {
12936
- child.once("error", () => resolve23(1));
12937
- child.once("close", (code) => resolve23(code ?? 1));
13064
+ const exitCode = await new Promise((resolve24) => {
13065
+ child.once("error", () => resolve24(1));
13066
+ child.once("close", (code) => resolve24(code ?? 1));
12938
13067
  });
12939
13068
  for (const pendingLog of flushPendingClaudeToolUseLogs({
12940
13069
  runId: input.runId,
@@ -13075,8 +13204,8 @@ async function executeTest(context, args) {
13075
13204
  init_runner();
13076
13205
  init__parsers();
13077
13206
  init__paths();
13078
- import { existsSync as existsSync16, mkdirSync as mkdirSync10, readdirSync as readdirSync3, writeFileSync as writeFileSync8 } from "fs";
13079
- import { resolve as resolve23 } from "path";
13207
+ import { existsSync as existsSync16, mkdirSync as mkdirSync11, readdirSync as readdirSync3, writeFileSync as writeFileSync9 } from "fs";
13208
+ import { resolve as resolve24 } from "path";
13080
13209
  import { createPluginHost } from "@rig/core";
13081
13210
  import {
13082
13211
  isSupportedBunVersion as isSupportedBunVersion2,
@@ -13131,12 +13260,12 @@ function runSetupInit(projectRoot) {
13131
13260
  const stateDir = resolveControlPlaneHostStateDir(projectRoot);
13132
13261
  const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
13133
13262
  const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
13134
- mkdirSync10(stateDir, { recursive: true });
13135
- mkdirSync10(logsDir, { recursive: true });
13136
- mkdirSync10(artifactsDir, { recursive: true });
13137
- const failuresPath = resolve23(stateDir, "failed_approaches.md");
13263
+ mkdirSync11(stateDir, { recursive: true });
13264
+ mkdirSync11(logsDir, { recursive: true });
13265
+ mkdirSync11(artifactsDir, { recursive: true });
13266
+ const failuresPath = resolve24(stateDir, "failed_approaches.md");
13138
13267
  if (!existsSync16(failuresPath)) {
13139
- writeFileSync8(failuresPath, `# Failed Approaches
13268
+ writeFileSync9(failuresPath, `# Failed Approaches
13140
13269
 
13141
13270
  `, "utf-8");
13142
13271
  }
@@ -13153,17 +13282,17 @@ async function runSetupCheck(projectRoot, outputMode = "text") {
13153
13282
  }
13154
13283
  async function runSetupPreflight(projectRoot, outputMode = "text") {
13155
13284
  await runSetupCheck(projectRoot, outputMode);
13156
- const validationRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
13285
+ const validationRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
13157
13286
  if (existsSync16(validationRoot)) {
13158
13287
  const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
13159
13288
  for (const validator of validators) {
13160
- const script = resolve23(validationRoot, validator.name, "validate.sh");
13289
+ const script = resolve24(validationRoot, validator.name, "validate.sh");
13161
13290
  if (existsSync16(script)) {
13162
13291
  console.log(`OK: validator script ${script}`);
13163
13292
  }
13164
13293
  }
13165
13294
  }
13166
- const hooksRoot = resolve23(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
13295
+ const hooksRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
13167
13296
  if (existsSync16(hooksRoot)) {
13168
13297
  const hooks = readdirSync3(hooksRoot).filter((name) => name.endsWith(".sh"));
13169
13298
  for (const hook of hooks) {
@@ -13310,7 +13439,7 @@ var PROJECT_REQUIRED_GROUPS = new Set([
13310
13439
  ]);
13311
13440
  var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
13312
13441
  function hasInitializedRigProject(projectRoot) {
13313
- return RIG_CONFIG_FILENAMES.some((name) => existsSync18(resolve24(projectRoot, name))) || existsSync18(resolve24(projectRoot, ".rig"));
13442
+ return RIG_CONFIG_FILENAMES.some((name) => existsSync18(resolve25(projectRoot, name))) || existsSync18(resolve25(projectRoot, ".rig"));
13314
13443
  }
13315
13444
  function requireInitializedRigProject(context, group) {
13316
13445
  if (hasInitializedRigProject(context.projectRoot)) {
@@ -13364,7 +13493,7 @@ function resolveTopLevelLaunchState(context) {
13364
13493
  let selectedServer = null;
13365
13494
  if (projectInitialized) {
13366
13495
  try {
13367
- const statePath = resolve24(context.projectRoot, ".rig", "state", "connection.json");
13496
+ const statePath = resolve25(context.projectRoot, ".rig", "state", "connection.json");
13368
13497
  if (existsSync18(statePath)) {
13369
13498
  const parsed = JSON.parse(readFileSync13(statePath, "utf-8"));
13370
13499
  selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
@@ -13373,8 +13502,14 @@ function resolveTopLevelLaunchState(context) {
13373
13502
  }
13374
13503
  return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
13375
13504
  }
13505
+ function envTruthy(value) {
13506
+ if (!value)
13507
+ return false;
13508
+ const normalized = value.trim().toLowerCase();
13509
+ return normalized !== "0" && normalized !== "false" && normalized !== "no";
13510
+ }
13376
13511
  function shouldOpenApp(context) {
13377
- return context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
13512
+ 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);
13378
13513
  }
13379
13514
  async function openApp(context, options = {}) {
13380
13515
  const { runOperatorBoardLoop: runOperatorBoardLoop2 } = await Promise.resolve().then(() => (init_board(), exports_board));