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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/dist/bin/build-rig-binaries.js +8 -40
  2. package/dist/bin/rig.js +12519 -26675
  3. package/dist/src/app/board.js +74 -693
  4. package/dist/src/app/drone-ui.js +1 -1
  5. package/dist/src/app/theme.js +0 -1
  6. package/dist/src/commands/_async-ui.js +1 -1
  7. package/dist/src/commands/_authority-runs.d.ts +1 -1
  8. package/dist/src/commands/_authority-runs.js +12 -2
  9. package/dist/src/commands/_cli-format.d.ts +1 -10
  10. package/dist/src/commands/_cli-format.js +2 -5
  11. package/dist/src/commands/_connection-state.d.ts +1 -11
  12. package/dist/src/commands/_connection-state.js +5 -50
  13. package/dist/src/commands/_doctor-checks.js +40 -501
  14. package/dist/src/commands/_help-catalog.js +17 -99
  15. package/dist/src/commands/_json-output.js +0 -4
  16. package/dist/src/commands/_operator-view.js +54 -575
  17. package/dist/src/commands/_pi-frontend.d.ts +0 -27
  18. package/dist/src/commands/_pi-frontend.js +52 -576
  19. package/dist/src/commands/_preflight.js +66 -553
  20. package/dist/src/commands/_server-client.d.ts +0 -33
  21. package/dist/src/commands/_server-client.js +46 -541
  22. package/dist/src/commands/_snapshot-upload.js +42 -503
  23. package/dist/src/commands/_spinner.js +1 -1
  24. package/dist/src/commands/agent.js +12 -2
  25. package/dist/src/commands/browser.js +1 -1
  26. package/dist/src/commands/connect.js +15 -626
  27. package/dist/src/commands/doctor.js +41 -502
  28. package/dist/src/commands/github.js +51 -584
  29. package/dist/src/commands/inbox.js +41 -502
  30. package/dist/src/commands/init.js +74 -561
  31. package/dist/src/commands/inspect.js +41 -502
  32. package/dist/src/commands/run.js +54 -578
  33. package/dist/src/commands/server.js +163 -692
  34. package/dist/src/commands/setup.js +46 -507
  35. package/dist/src/commands/stats.js +58 -601
  36. package/dist/src/commands/task-run-driver.js +58 -509
  37. package/dist/src/commands/task.js +110 -729
  38. package/dist/src/commands.js +237 -1112
  39. package/dist/src/index.js +244 -1123
  40. package/dist/src/launcher.js +0 -4
  41. package/package.json +9 -13
  42. package/dist/src/app-opentui/adapters/command.d.ts +0 -2
  43. package/dist/src/app-opentui/adapters/command.js +0 -329
  44. package/dist/src/app-opentui/adapters/common.d.ts +0 -56
  45. package/dist/src/app-opentui/adapters/common.js +0 -153
  46. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -9
  47. package/dist/src/app-opentui/adapters/doctor.js +0 -1217
  48. package/dist/src/app-opentui/adapters/family.d.ts +0 -62
  49. package/dist/src/app-opentui/adapters/family.js +0 -14855
  50. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -14
  51. package/dist/src/app-opentui/adapters/fleet.js +0 -1335
  52. package/dist/src/app-opentui/adapters/inbox.d.ts +0 -43
  53. package/dist/src/app-opentui/adapters/inbox.js +0 -1944
  54. package/dist/src/app-opentui/adapters/init.d.ts +0 -11
  55. package/dist/src/app-opentui/adapters/init.js +0 -2818
  56. package/dist/src/app-opentui/adapters/inspect.d.ts +0 -52
  57. package/dist/src/app-opentui/adapters/inspect.js +0 -1455
  58. package/dist/src/app-opentui/adapters/pi-attach.d.ts +0 -32
  59. package/dist/src/app-opentui/adapters/pi-attach.js +0 -2101
  60. package/dist/src/app-opentui/adapters/pi.d.ts +0 -23
  61. package/dist/src/app-opentui/adapters/pi.js +0 -363
  62. package/dist/src/app-opentui/adapters/plugin.d.ts +0 -84
  63. package/dist/src/app-opentui/adapters/plugin.js +0 -544
  64. package/dist/src/app-opentui/adapters/repo.d.ts +0 -37
  65. package/dist/src/app-opentui/adapters/repo.js +0 -186
  66. package/dist/src/app-opentui/adapters/run-detail.d.ts +0 -27
  67. package/dist/src/app-opentui/adapters/run-detail.js +0 -1441
  68. package/dist/src/app-opentui/adapters/server.d.ts +0 -48
  69. package/dist/src/app-opentui/adapters/server.js +0 -1561
  70. package/dist/src/app-opentui/adapters/tasks.d.ts +0 -64
  71. package/dist/src/app-opentui/adapters/tasks.js +0 -4524
  72. package/dist/src/app-opentui/adapters/workspace.d.ts +0 -49
  73. package/dist/src/app-opentui/adapters/workspace.js +0 -333
  74. package/dist/src/app-opentui/autocomplete.d.ts +0 -20
  75. package/dist/src/app-opentui/autocomplete.js +0 -578
  76. package/dist/src/app-opentui/bootstrap.d.ts +0 -11
  77. package/dist/src/app-opentui/bootstrap.js +0 -27833
  78. package/dist/src/app-opentui/command-palette.d.ts +0 -3
  79. package/dist/src/app-opentui/command-palette.js +0 -1038
  80. package/dist/src/app-opentui/command-pty-host.d.ts +0 -62
  81. package/dist/src/app-opentui/command-pty-host.js +0 -248
  82. package/dist/src/app-opentui/drone.d.ts +0 -12
  83. package/dist/src/app-opentui/drone.js +0 -230
  84. package/dist/src/app-opentui/events.d.ts +0 -7
  85. package/dist/src/app-opentui/events.js +0 -28
  86. package/dist/src/app-opentui/fleet-stats.d.ts +0 -32
  87. package/dist/src/app-opentui/fleet-stats.js +0 -114
  88. package/dist/src/app-opentui/focus-manager.d.ts +0 -14
  89. package/dist/src/app-opentui/focus-manager.js +0 -24
  90. package/dist/src/app-opentui/index.d.ts +0 -8
  91. package/dist/src/app-opentui/index.js +0 -5260
  92. package/dist/src/app-opentui/intent.d.ts +0 -3
  93. package/dist/src/app-opentui/intent.js +0 -365
  94. package/dist/src/app-opentui/keymap.d.ts +0 -21
  95. package/dist/src/app-opentui/keymap.js +0 -1377
  96. package/dist/src/app-opentui/launch-routing.d.ts +0 -16
  97. package/dist/src/app-opentui/launch-routing.js +0 -55
  98. package/dist/src/app-opentui/layout.d.ts +0 -22
  99. package/dist/src/app-opentui/layout.js +0 -51
  100. package/dist/src/app-opentui/list-search.d.ts +0 -36
  101. package/dist/src/app-opentui/list-search.js +0 -130
  102. package/dist/src/app-opentui/pi-host-child.d.ts +0 -2
  103. package/dist/src/app-opentui/pi-host-child.js +0 -1299
  104. package/dist/src/app-opentui/pi-pty-host.d.ts +0 -28
  105. package/dist/src/app-opentui/pi-pty-host.js +0 -10
  106. package/dist/src/app-opentui/react/App.d.ts +0 -9
  107. package/dist/src/app-opentui/react/App.js +0 -3866
  108. package/dist/src/app-opentui/react/Backdrop.d.ts +0 -5
  109. package/dist/src/app-opentui/react/Backdrop.js +0 -823
  110. package/dist/src/app-opentui/react/ChromeHost.d.ts +0 -5
  111. package/dist/src/app-opentui/react/ChromeHost.js +0 -1539
  112. package/dist/src/app-opentui/react/SceneFrameView.d.ts +0 -7
  113. package/dist/src/app-opentui/react/SceneFrameView.js +0 -579
  114. package/dist/src/app-opentui/react/context.d.ts +0 -17
  115. package/dist/src/app-opentui/react/context.js +0 -37
  116. package/dist/src/app-opentui/react/launch.d.ts +0 -2
  117. package/dist/src/app-opentui/react/launch.js +0 -4897
  118. package/dist/src/app-opentui/react/nav.d.ts +0 -18
  119. package/dist/src/app-opentui/react/nav.js +0 -54
  120. package/dist/src/app-opentui/react/scroll.d.ts +0 -12
  121. package/dist/src/app-opentui/react/scroll.js +0 -21
  122. package/dist/src/app-opentui/react/syntax.d.ts +0 -2
  123. package/dist/src/app-opentui/react/syntax.js +0 -65
  124. package/dist/src/app-opentui/registry.d.ts +0 -4
  125. package/dist/src/app-opentui/registry.js +0 -22876
  126. package/dist/src/app-opentui/remote-link.d.ts +0 -10
  127. package/dist/src/app-opentui/remote-link.js +0 -47
  128. package/dist/src/app-opentui/render/ascii-fleet.d.ts +0 -15
  129. package/dist/src/app-opentui/render/ascii-fleet.js +0 -82
  130. package/dist/src/app-opentui/render/constants.d.ts +0 -30
  131. package/dist/src/app-opentui/render/constants.js +0 -64
  132. package/dist/src/app-opentui/render/graphics.d.ts +0 -40
  133. package/dist/src/app-opentui/render/graphics.js +0 -713
  134. package/dist/src/app-opentui/render/hover.d.ts +0 -11
  135. package/dist/src/app-opentui/render/hover.js +0 -34
  136. package/dist/src/app-opentui/render/native-host.d.ts +0 -37
  137. package/dist/src/app-opentui/render/native-host.js +0 -180
  138. package/dist/src/app-opentui/render/panel-layout.d.ts +0 -38
  139. package/dist/src/app-opentui/render/panel-layout.js +0 -48
  140. package/dist/src/app-opentui/render/panels.d.ts +0 -12
  141. package/dist/src/app-opentui/render/panels.js +0 -288
  142. package/dist/src/app-opentui/render/preloader.d.ts +0 -10
  143. package/dist/src/app-opentui/render/preloader.js +0 -166
  144. package/dist/src/app-opentui/render/scene.d.ts +0 -68
  145. package/dist/src/app-opentui/render/scene.js +0 -300
  146. package/dist/src/app-opentui/render/terminal-handoff.d.ts +0 -16
  147. package/dist/src/app-opentui/render/terminal-handoff.js +0 -14
  148. package/dist/src/app-opentui/render/text.d.ts +0 -29
  149. package/dist/src/app-opentui/render/text.js +0 -177
  150. package/dist/src/app-opentui/render/type-bar.d.ts +0 -15
  151. package/dist/src/app-opentui/render/type-bar.js +0 -212
  152. package/dist/src/app-opentui/runtime-resources.d.ts +0 -16
  153. package/dist/src/app-opentui/runtime-resources.js +0 -62
  154. package/dist/src/app-opentui/runtime.d.ts +0 -45
  155. package/dist/src/app-opentui/runtime.js +0 -5232
  156. package/dist/src/app-opentui/scenes/command.d.ts +0 -3
  157. package/dist/src/app-opentui/scenes/command.js +0 -118
  158. package/dist/src/app-opentui/scenes/doctor.d.ts +0 -3
  159. package/dist/src/app-opentui/scenes/doctor.js +0 -296
  160. package/dist/src/app-opentui/scenes/error.d.ts +0 -2
  161. package/dist/src/app-opentui/scenes/error.js +0 -277
  162. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +0 -2
  163. package/dist/src/app-opentui/scenes/family-domains/agent.js +0 -349
  164. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +0 -2
  165. package/dist/src/app-opentui/scenes/family-domains/browser.js +0 -196
  166. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +0 -2
  167. package/dist/src/app-opentui/scenes/family-domains/dist.js +0 -244
  168. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +0 -2
  169. package/dist/src/app-opentui/scenes/family-domains/git.js +0 -196
  170. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +0 -2
  171. package/dist/src/app-opentui/scenes/family-domains/github.js +0 -275
  172. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +0 -2
  173. package/dist/src/app-opentui/scenes/family-domains/harness.js +0 -153
  174. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +0 -4
  175. package/dist/src/app-opentui/scenes/family-domains/index.js +0 -1680
  176. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +0 -76
  177. package/dist/src/app-opentui/scenes/family-domains/kit.js +0 -306
  178. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +0 -2
  179. package/dist/src/app-opentui/scenes/family-domains/profile.js +0 -213
  180. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +0 -2
  181. package/dist/src/app-opentui/scenes/family-domains/queue.js +0 -147
  182. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +0 -2
  183. package/dist/src/app-opentui/scenes/family-domains/remote.js +0 -519
  184. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +0 -2
  185. package/dist/src/app-opentui/scenes/family-domains/review.js +0 -281
  186. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +0 -2
  187. package/dist/src/app-opentui/scenes/family-domains/setup.js +0 -268
  188. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +0 -2
  189. package/dist/src/app-opentui/scenes/family-domains/stats.js +0 -371
  190. package/dist/src/app-opentui/scenes/family.d.ts +0 -3
  191. package/dist/src/app-opentui/scenes/family.js +0 -2199
  192. package/dist/src/app-opentui/scenes/fleet.d.ts +0 -3
  193. package/dist/src/app-opentui/scenes/fleet.js +0 -766
  194. package/dist/src/app-opentui/scenes/handoff.d.ts +0 -2
  195. package/dist/src/app-opentui/scenes/handoff.js +0 -455
  196. package/dist/src/app-opentui/scenes/help.d.ts +0 -3
  197. package/dist/src/app-opentui/scenes/help.js +0 -725
  198. package/dist/src/app-opentui/scenes/inbox.d.ts +0 -3
  199. package/dist/src/app-opentui/scenes/inbox.js +0 -427
  200. package/dist/src/app-opentui/scenes/init.d.ts +0 -3
  201. package/dist/src/app-opentui/scenes/init.js +0 -181
  202. package/dist/src/app-opentui/scenes/inspect.d.ts +0 -3
  203. package/dist/src/app-opentui/scenes/inspect.js +0 -794
  204. package/dist/src/app-opentui/scenes/main.d.ts +0 -3
  205. package/dist/src/app-opentui/scenes/main.js +0 -332
  206. package/dist/src/app-opentui/scenes/pi.d.ts +0 -3
  207. package/dist/src/app-opentui/scenes/pi.js +0 -509
  208. package/dist/src/app-opentui/scenes/plugin.d.ts +0 -3
  209. package/dist/src/app-opentui/scenes/plugin.js +0 -487
  210. package/dist/src/app-opentui/scenes/repo.d.ts +0 -3
  211. package/dist/src/app-opentui/scenes/repo.js +0 -425
  212. package/dist/src/app-opentui/scenes/run-detail.d.ts +0 -3
  213. package/dist/src/app-opentui/scenes/run-detail.js +0 -467
  214. package/dist/src/app-opentui/scenes/server.d.ts +0 -3
  215. package/dist/src/app-opentui/scenes/server.js +0 -378
  216. package/dist/src/app-opentui/scenes/tasks.d.ts +0 -3
  217. package/dist/src/app-opentui/scenes/tasks.js +0 -768
  218. package/dist/src/app-opentui/scenes/workspace.d.ts +0 -3
  219. package/dist/src/app-opentui/scenes/workspace.js +0 -427
  220. package/dist/src/app-opentui/selectable.d.ts +0 -19
  221. package/dist/src/app-opentui/selectable.js +0 -80
  222. package/dist/src/app-opentui/state.d.ts +0 -4
  223. package/dist/src/app-opentui/state.js +0 -399
  224. package/dist/src/app-opentui/surface-catalog.d.ts +0 -20
  225. package/dist/src/app-opentui/surface-catalog.js +0 -542
  226. package/dist/src/app-opentui/theme.d.ts +0 -59
  227. package/dist/src/app-opentui/theme.js +0 -142
  228. package/dist/src/app-opentui/types.d.ts +0 -313
  229. package/dist/src/app-opentui/types.js +0 -1
  230. package/dist/src/commands/_server-events.d.ts +0 -26
  231. package/dist/src/commands/_server-events.js +0 -715
package/dist/src/index.js CHANGED
@@ -296,7 +296,6 @@ function statusColor(status) {
296
296
  case "validating":
297
297
  case "reviewing":
298
298
  case "closing-out":
299
- case "stopping":
300
299
  return cyan;
301
300
  case "needs-attention":
302
301
  case "needs_attention":
@@ -433,7 +432,7 @@ function createTtySpinner(input) {
433
432
  output.write("\r\x1B[2K");
434
433
  };
435
434
  render();
436
- const timer = isTty ? setInterval(render, input.intervalMs ?? 16) : null;
435
+ const timer = isTty ? setInterval(render, input.intervalMs ?? 120) : null;
437
436
  return {
438
437
  setLabel(next) {
439
438
  label = next;
@@ -1053,28 +1052,12 @@ function readRepoConnection(projectRoot) {
1053
1052
  selected,
1054
1053
  project: typeof record.project === "string" ? record.project : undefined,
1055
1054
  linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
1056
- serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined,
1057
- serverProjectRootAlias: typeof record.serverProjectRootAlias === "string" && record.serverProjectRootAlias.trim() ? record.serverProjectRootAlias.trim() : undefined,
1058
- serverProjectRootBaseUrl: typeof record.serverProjectRootBaseUrl === "string" && record.serverProjectRootBaseUrl.trim() ? record.serverProjectRootBaseUrl.trim().replace(/\/+$/, "") : undefined
1055
+ serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
1059
1056
  };
1060
1057
  }
1061
1058
  function writeRepoConnection(projectRoot, state) {
1062
1059
  writeJsonFile2(resolveRepoConnectionPath(projectRoot), state);
1063
1060
  }
1064
- function rootAllowedForSelection(repo, connection) {
1065
- const root = repo.serverProjectRoot?.trim();
1066
- if (!root)
1067
- return;
1068
- if (connection.kind === "remote") {
1069
- if (repo.serverProjectRootAlias !== repo.selected)
1070
- return;
1071
- if (repo.serverProjectRootBaseUrl !== connection.baseUrl)
1072
- return;
1073
- } else if (repo.serverProjectRootAlias && repo.serverProjectRootAlias !== repo.selected) {
1074
- return;
1075
- }
1076
- return root;
1077
- }
1078
1061
  function resolveSelectedConnection(projectRoot, options = {}) {
1079
1062
  const repo = readRepoConnection(projectRoot);
1080
1063
  if (!repo)
@@ -1086,41 +1069,13 @@ function resolveSelectedConnection(projectRoot, options = {}) {
1086
1069
  if (!connection) {
1087
1070
  throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
1088
1071
  }
1089
- return { alias: repo.selected, connection, serverProjectRoot: rootAllowedForSelection(repo, connection) };
1072
+ return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
1090
1073
  }
1091
- function writeRepoServerProjectRoot(projectRoot, serverProjectRoot, metadata = {}) {
1074
+ function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
1092
1075
  const repo = readRepoConnection(projectRoot);
1093
1076
  if (!repo)
1094
1077
  return;
1095
- let inferred = metadata;
1096
- if (!inferred.alias || !inferred.baseUrl) {
1097
- try {
1098
- const selected = resolveSelectedConnection(projectRoot);
1099
- if (selected?.connection.kind === "remote") {
1100
- inferred = {
1101
- alias: inferred.alias ?? selected.alias,
1102
- baseUrl: inferred.baseUrl ?? selected.connection.baseUrl
1103
- };
1104
- }
1105
- } catch {}
1106
- }
1107
- writeRepoConnection(projectRoot, {
1108
- ...repo,
1109
- ...metadata.project ? { project: metadata.project } : {},
1110
- serverProjectRoot,
1111
- ...inferred.alias ? { serverProjectRootAlias: inferred.alias } : {},
1112
- ...inferred.baseUrl ? { serverProjectRootBaseUrl: inferred.baseUrl.replace(/\/+$/, "") } : {}
1113
- });
1114
- }
1115
- function clearRepoServerProjectRoot(projectRoot) {
1116
- const repo = readRepoConnection(projectRoot);
1117
- if (!repo)
1118
- return;
1119
- writeRepoConnection(projectRoot, {
1120
- selected: repo.selected,
1121
- ...repo.project ? { project: repo.project } : {},
1122
- ...repo.linkedAt ? { linkedAt: repo.linkedAt } : {}
1123
- });
1078
+ writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
1124
1079
  }
1125
1080
  function isRemoteConnectionSelected(projectRoot) {
1126
1081
  return resolveSelectedConnection(projectRoot)?.connection.kind === "remote";
@@ -1130,8 +1085,8 @@ var init__connection_state = __esm(() => {
1130
1085
  });
1131
1086
 
1132
1087
  // packages/cli/src/commands/_server-client.ts
1133
- import { existsSync as existsSync7, mkdirSync as mkdirSync7, readFileSync as readFileSync4, writeFileSync as writeFileSync5 } from "fs";
1134
- import { dirname as dirname3, isAbsolute, resolve as resolve11 } from "path";
1088
+ import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
1089
+ import { resolve as resolve11 } from "path";
1135
1090
  import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
1136
1091
  function setServerPhaseListener(listener) {
1137
1092
  const previous = serverPhaseListener;
@@ -1149,21 +1104,17 @@ function setGitHubBearerTokenForCurrentProcess(token, projectRoot) {
1149
1104
  const scopedKey = resolve11(projectRoot ?? process.cwd());
1150
1105
  scopedGitHubBearerTokens.set(scopedKey, cleanToken(token ?? undefined));
1151
1106
  }
1152
- function readRemoteAuthState(projectRoot) {
1107
+ function readPrivateRemoteSessionToken(projectRoot) {
1153
1108
  const path = resolve11(projectRoot, ".rig", "state", "github-auth.json");
1154
1109
  if (!existsSync7(path))
1155
1110
  return null;
1156
1111
  try {
1157
1112
  const parsed = JSON.parse(readFileSync4(path, "utf8"));
1158
- return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
1113
+ return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
1159
1114
  } catch {
1160
1115
  return null;
1161
1116
  }
1162
1117
  }
1163
- function readPrivateRemoteSessionToken(projectRoot) {
1164
- const parsed = readRemoteAuthState(projectRoot);
1165
- return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
1166
- }
1167
1118
  function readGitHubBearerTokenForRemote(projectRoot) {
1168
1119
  const scopedKey = resolve11(projectRoot);
1169
1120
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -1174,421 +1125,18 @@ function readGitHubBearerTokenForRemote(projectRoot) {
1174
1125
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
1175
1126
  }
1176
1127
  function readStoredGitHubAuthToken(projectRoot) {
1177
- const parsed = readRemoteAuthState(projectRoot);
1178
- return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
1179
- }
1180
- function inferRemoteServerProjectRootCandidateFromAuthState(projectRoot, repoSlug) {
1181
- if (!/^[^/]+\/[^/]+$/.test(repoSlug))
1182
- return null;
1183
- const repo = readRepoConnection(projectRoot);
1184
- const auth = readRemoteAuthState(projectRoot);
1185
- const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
1186
- const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
1187
- if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
1188
- return null;
1189
- const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
1190
- if (!checkoutBaseDir)
1191
- return null;
1192
- return `${checkoutBaseDir.replace(/\/+$/, "")}/${repoSlug}`;
1193
- }
1194
- function readLocalConnectionFallbackToken(projectRoot) {
1195
- return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
1196
- }
1197
- function normalizeRepoSlug(value) {
1198
- const slug = value?.trim();
1199
- return slug && /^[^/\s]+\/[^/\s]+$/.test(slug) ? slug : null;
1200
- }
1201
- function readProjectLinkSlug(projectRoot) {
1202
- const path = resolve11(projectRoot, ".rig", "state", "project-link.json");
1128
+ const path = resolve11(projectRoot, ".rig", "state", "github-auth.json");
1203
1129
  if (!existsSync7(path))
1204
1130
  return null;
1205
1131
  try {
1206
1132
  const parsed = JSON.parse(readFileSync4(path, "utf8"));
1207
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
1208
- return null;
1209
- return normalizeRepoSlug(typeof parsed.repoSlug === "string" ? String(parsed.repoSlug) : null);
1133
+ return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
1210
1134
  } catch {
1211
1135
  return null;
1212
1136
  }
1213
1137
  }
1214
- function writeProjectLinkConnection(projectRoot, repoSlug, alias) {
1215
- const path = resolve11(projectRoot, ".rig", "state", "project-link.json");
1216
- mkdirSync7(dirname3(path), { recursive: true });
1217
- writeFileSync5(path, `${JSON.stringify({ repoSlug, connection: alias, linkedAt: new Date().toISOString() }, null, 2)}
1218
- `, "utf8");
1219
- }
1220
- function remoteLinkRepairCommand(repoSlug) {
1221
- return repoSlug ? `rig server repair-link --repo ${repoSlug}` : "rig server repair-link --repo owner/repo";
1222
- }
1223
- function formatRemoteProjectLinkHint(resolution) {
1224
- const repair = remoteLinkRepairCommand(resolution.repoSlug);
1225
- if (resolution.status === "auth_required") {
1226
- return `Authenticate the selected remote${resolution.alias ? ` (${resolution.alias})` : ""}, then run \`${repair}\`. Use \`rig github auth import-gh\` or \`rig init --repair --server remote --github-auth device${resolution.repoSlug ? ` --repo ${resolution.repoSlug}` : ""}\`.`;
1227
- }
1228
- if (resolution.status === "missing_project") {
1229
- return `Record the repo slug, then run \`${repair}\` (or \`rig init --repo owner/repo --server remote --github-auth device\`).`;
1230
- }
1231
- if (resolution.status === "not_remote")
1232
- return "Select a remote server with `rig server use <alias>` before repairing a remote project link.";
1233
- return `Run \`${repair}\` to backfill or prepare a server-host checkout for the selected remote${resolution.alias ? ` (${resolution.alias})` : ""}.`;
1234
- }
1235
- function remoteProjectLinkFailure(input) {
1236
- const partial = {
1237
- status: input.status,
1238
- alias: input.alias,
1239
- baseUrl: input.baseUrl,
1240
- repoSlug: input.repoSlug
1241
- };
1242
- return {
1243
- ok: false,
1244
- ...input,
1245
- hint: formatRemoteProjectLinkHint(partial),
1246
- next: remoteLinkRepairCommand(input.repoSlug)
1247
- };
1248
- }
1249
- function remoteProjectLinkSuccess(input) {
1250
- return {
1251
- ok: true,
1252
- status: input.status,
1253
- alias: input.alias,
1254
- baseUrl: input.baseUrl,
1255
- repoSlug: input.repoSlug,
1256
- serverProjectRoot: input.serverProjectRoot,
1257
- source: input.source,
1258
- prepared: input.prepared ?? input.status === "prepared",
1259
- validated: input.validated ?? false,
1260
- message: input.message ?? `Remote project link ready for ${input.repoSlug}.`,
1261
- hint: "Remote-scoped task/run/status requests will send x-rig-project-root for this server-host checkout.",
1262
- next: "rig task list"
1263
- };
1264
- }
1265
- function localCheckoutPathCandidate(projectRoot, candidate) {
1266
- try {
1267
- const local = resolve11(projectRoot);
1268
- const resolved = resolve11(candidate);
1269
- return resolved === local || resolved.startsWith(`${local}/`);
1270
- } catch {
1271
- return false;
1272
- }
1273
- }
1274
- async function requestRemoteProjectLinkJson(baseUrl, pathname, authToken, init = {}) {
1275
- const requestUrl = new URL(`${baseUrl}${pathname}`);
1276
- if (authToken && queryAuthFallbackEnabled())
1277
- requestUrl.searchParams.set("rt", authToken);
1278
- const response = await fetch(requestUrl, {
1279
- ...init,
1280
- headers: mergeHeaders(init.headers, authToken)
1281
- });
1282
- const text = await response.text();
1283
- const payload = text.trim().length > 0 ? (() => {
1284
- try {
1285
- return JSON.parse(text);
1286
- } catch {
1287
- return null;
1288
- }
1289
- })() : null;
1290
- return { ok: response.ok, status: response.status, payload, text };
1291
- }
1292
- function payloadError(payload, fallback) {
1293
- if (payload && typeof payload === "object" && !Array.isArray(payload)) {
1294
- const record = payload;
1295
- const value = record.error ?? record.message ?? record.reason;
1296
- if (typeof value === "string" && value.trim())
1297
- return value.trim();
1298
- }
1299
- return fallback;
1300
- }
1301
- function checkoutPathsFromProjectPayload(payload) {
1302
- if (!payload || typeof payload !== "object" || Array.isArray(payload))
1303
- return [];
1304
- const project = payload.project;
1305
- if (!project || typeof project !== "object" || Array.isArray(project))
1306
- return [];
1307
- const checkouts = project.checkouts;
1308
- if (!Array.isArray(checkouts))
1309
- return [];
1310
- return [...checkouts].reverse().flatMap((entry) => {
1311
- if (!entry || typeof entry !== "object" || Array.isArray(entry))
1312
- return [];
1313
- const path = entry.path;
1314
- return typeof path === "string" && path.trim() ? [path.trim()] : [];
1315
- });
1316
- }
1317
- function checkoutPathFromPreparePayload(payload) {
1318
- if (!payload || typeof payload !== "object" || Array.isArray(payload))
1319
- return null;
1320
- const checkout = payload.checkout;
1321
- if (!checkout || typeof checkout !== "object" || Array.isArray(checkout))
1322
- return null;
1323
- const path = checkout.path;
1324
- return typeof path === "string" && path.trim() ? path.trim() : null;
1325
- }
1326
- async function validateAndPersistRemoteRoot(input) {
1327
- const candidate = input.candidate.trim();
1328
- if (!candidate || !isAbsolute(candidate)) {
1329
- return remoteProjectLinkFailure({
1330
- status: "invalid_root",
1331
- alias: input.alias,
1332
- baseUrl: input.baseUrl,
1333
- repoSlug: input.repoSlug,
1334
- message: `Remote project root candidate is not an absolute server-host path: ${candidate || "(empty)"}.`
1335
- });
1336
- }
1337
- if (localCheckoutPathCandidate(input.projectRoot, candidate)) {
1338
- return remoteProjectLinkFailure({
1339
- status: "invalid_root",
1340
- alias: input.alias,
1341
- baseUrl: input.baseUrl,
1342
- repoSlug: input.repoSlug,
1343
- message: `Refusing to use local checkout path ${candidate} as a remote server project root.`
1344
- });
1345
- }
1346
- let response;
1347
- try {
1348
- response = await requestRemoteProjectLinkJson(input.baseUrl, "/api/server/project-root", input.authToken, {
1349
- method: "POST",
1350
- headers: { "content-type": "application/json" },
1351
- body: JSON.stringify({ projectRoot: candidate })
1352
- });
1353
- } catch (error) {
1354
- return remoteProjectLinkFailure({
1355
- status: "error",
1356
- alias: input.alias,
1357
- baseUrl: input.baseUrl,
1358
- repoSlug: input.repoSlug,
1359
- message: `Could not validate remote project root ${candidate}: ${error instanceof Error ? error.message : String(error)}`
1360
- });
1361
- }
1362
- if (response.status === 401 || response.status === 403) {
1363
- return remoteProjectLinkFailure({
1364
- status: "auth_required",
1365
- alias: input.alias,
1366
- baseUrl: input.baseUrl,
1367
- repoSlug: input.repoSlug,
1368
- statusCode: response.status,
1369
- message: `Remote server ${input.alias} requires authentication before validating project root ${candidate}.`
1370
- });
1371
- }
1372
- if (!response.ok) {
1373
- return remoteProjectLinkFailure({
1374
- status: "invalid_root",
1375
- alias: input.alias,
1376
- baseUrl: input.baseUrl,
1377
- repoSlug: input.repoSlug,
1378
- statusCode: response.status,
1379
- message: `Remote server rejected project root ${candidate} (${response.status}): ${payloadError(response.payload, response.text || "project-root validation failed")}`
1380
- });
1381
- }
1382
- const record = response.payload && typeof response.payload === "object" && !Array.isArray(response.payload) ? response.payload : {};
1383
- if (record.ok !== true) {
1384
- return remoteProjectLinkFailure({
1385
- status: "invalid_root",
1386
- alias: input.alias,
1387
- baseUrl: input.baseUrl,
1388
- repoSlug: input.repoSlug,
1389
- message: `Remote server did not accept project root ${candidate}: ${payloadError(response.payload, "project-root validation failed")}`
1390
- });
1391
- }
1392
- const accepted = typeof record.projectRoot === "string" && record.projectRoot.trim() ? record.projectRoot.trim() : typeof record.requestedProjectRoot === "string" && record.requestedProjectRoot.trim() ? record.requestedProjectRoot.trim() : candidate;
1393
- writeRepoServerProjectRoot(input.projectRoot, accepted, { alias: input.alias, baseUrl: input.baseUrl, project: input.repoSlug });
1394
- writeProjectLinkConnection(input.projectRoot, input.repoSlug, input.alias);
1395
- const status = input.status ?? (input.prepared ? "prepared" : "backfilled");
1396
- return remoteProjectLinkSuccess({
1397
- status,
1398
- alias: input.alias,
1399
- baseUrl: input.baseUrl,
1400
- repoSlug: input.repoSlug,
1401
- serverProjectRoot: accepted,
1402
- source: input.source,
1403
- prepared: input.prepared,
1404
- validated: true,
1405
- message: status === "ready" ? `Remote project link already points to ${accepted} and was validated on ${input.alias}.` : input.prepared ? `Prepared and linked remote checkout ${accepted} for ${input.repoSlug}.` : `Backfilled remote checkout ${accepted} for ${input.repoSlug}.`
1406
- });
1407
- }
1408
- async function ensureRemoteProjectRootLink(projectRoot, options = {}) {
1409
- let selected;
1410
- try {
1411
- selected = resolveSelectedConnection(projectRoot);
1412
- } catch (error) {
1413
- return remoteProjectLinkFailure({ status: "error", message: error instanceof Error ? error.message : String(error) });
1414
- }
1415
- if (!selected || selected.connection.kind !== "remote") {
1416
- return remoteProjectLinkFailure({ status: "not_remote", message: "No remote Rig server is selected for this repo." });
1417
- }
1418
- const repo = readRepoConnection(projectRoot);
1419
- const explicitRepoRequested = options.repoSlug !== undefined;
1420
- const explicitRepoSlug = explicitRepoRequested ? normalizeRepoSlug(options.repoSlug) : null;
1421
- const repoProjectSlug = normalizeRepoSlug(repo?.project);
1422
- const repoSlug = explicitRepoSlug ?? repoProjectSlug ?? readProjectLinkSlug(projectRoot);
1423
- const alias = selected.alias;
1424
- const baseUrl = selected.connection.baseUrl;
1425
- const authToken = options.authToken === undefined ? readGitHubBearerTokenForRemote(projectRoot) : options.authToken;
1426
- const mode = options.mode ?? "backfill-only";
1427
- if (explicitRepoRequested && !explicitRepoSlug) {
1428
- return remoteProjectLinkFailure({
1429
- status: "missing_project",
1430
- alias,
1431
- baseUrl,
1432
- message: `Invalid --repo value ${JSON.stringify(options.repoSlug)}. Expected owner/repo.`
1433
- });
1434
- }
1435
- if (!repoSlug) {
1436
- return remoteProjectLinkFailure({
1437
- status: "missing_project",
1438
- alias,
1439
- baseUrl,
1440
- message: `Remote server ${alias} is selected, but this checkout has no GitHub repo slug recorded.`
1441
- });
1442
- }
1443
- const skippedCandidates = [];
1444
- const storedRoot = selected.serverProjectRoot?.trim() || null;
1445
- const storedRootMatchesResolvedRepo = repoProjectSlug === repoSlug;
1446
- if (storedRoot && storedRootMatchesResolvedRepo) {
1447
- if (localCheckoutPathCandidate(projectRoot, storedRoot)) {
1448
- clearRepoServerProjectRoot(projectRoot);
1449
- skippedCandidates.push(storedRoot);
1450
- } else {
1451
- const storedResult = await validateAndPersistRemoteRoot({
1452
- projectRoot,
1453
- alias,
1454
- baseUrl,
1455
- authToken,
1456
- repoSlug,
1457
- candidate: storedRoot,
1458
- source: "stored",
1459
- status: "ready"
1460
- });
1461
- if (storedResult.ok || storedResult.status === "auth_required" || storedResult.status === "error")
1462
- return storedResult;
1463
- clearRepoServerProjectRoot(projectRoot);
1464
- skippedCandidates.push(storedRoot);
1465
- }
1466
- } else if (storedRoot) {
1467
- skippedCandidates.push(storedRoot);
1468
- }
1469
- const authCandidate = inferRemoteServerProjectRootCandidateFromAuthState(projectRoot, repoSlug);
1470
- if (authCandidate) {
1471
- const authResult = await validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate: authCandidate, source: "auth-state" });
1472
- if (authResult.ok || authResult.status === "auth_required")
1473
- return authResult;
1474
- }
1475
- let registryResponse;
1476
- try {
1477
- registryResponse = await requestRemoteProjectLinkJson(baseUrl, `/api/projects/${encodeURIComponent(repoSlug)}`, authToken);
1478
- } catch (error) {
1479
- return remoteProjectLinkFailure({
1480
- status: "error",
1481
- alias,
1482
- baseUrl,
1483
- repoSlug,
1484
- message: `Could not read remote project registry for ${repoSlug} on ${alias}: ${error instanceof Error ? error.message : String(error)}`
1485
- });
1486
- }
1487
- if (registryResponse.status === 401 || registryResponse.status === 403) {
1488
- return remoteProjectLinkFailure({
1489
- status: "auth_required",
1490
- alias,
1491
- baseUrl,
1492
- repoSlug,
1493
- statusCode: registryResponse.status,
1494
- message: `Remote server ${alias} requires authentication before reading the ${repoSlug} project registry.`
1495
- });
1496
- }
1497
- if (registryResponse.ok) {
1498
- const candidates = checkoutPathsFromProjectPayload(registryResponse.payload);
1499
- for (const candidate of candidates) {
1500
- const result = await validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate, source: "registry" });
1501
- if (result.ok || result.status === "auth_required")
1502
- return result;
1503
- skippedCandidates.push(candidate);
1504
- }
1505
- if (mode === "backfill-only") {
1506
- return remoteProjectLinkFailure({
1507
- status: candidates.length > 0 ? "invalid_root" : "no_server_checkout",
1508
- alias,
1509
- baseUrl,
1510
- repoSlug,
1511
- message: candidates.length > 0 ? `Remote registry has checkout candidates for ${repoSlug}, but none validated for ${alias}.` : `Remote registry has ${repoSlug}, but no server checkout path is linked yet.`,
1512
- skippedCandidates
1513
- });
1514
- }
1515
- } else if (registryResponse.status === 404) {
1516
- if (mode === "backfill-only") {
1517
- return remoteProjectLinkFailure({
1518
- status: "project_not_registered",
1519
- alias,
1520
- baseUrl,
1521
- repoSlug,
1522
- statusCode: registryResponse.status,
1523
- message: `Remote server ${alias} has no registered project record for ${repoSlug}.`
1524
- });
1525
- }
1526
- } else {
1527
- return remoteProjectLinkFailure({
1528
- status: "error",
1529
- alias,
1530
- baseUrl,
1531
- repoSlug,
1532
- statusCode: registryResponse.status,
1533
- message: `Could not backfill ${repoSlug} from remote registry (${registryResponse.status}): ${payloadError(registryResponse.payload, registryResponse.text || "registry lookup failed")}`,
1534
- skippedCandidates
1535
- });
1536
- }
1537
- let prepareResponse;
1538
- try {
1539
- prepareResponse = await requestRemoteProjectLinkJson(baseUrl, `/api/projects/${encodeURIComponent(repoSlug)}/prepare-checkout`, authToken, {
1540
- method: "POST",
1541
- headers: { "content-type": "application/json" },
1542
- body: JSON.stringify({ checkout: { kind: "managed-clone" }, repoUrl: `https://github.com/${repoSlug}.git` })
1543
- });
1544
- } catch (error) {
1545
- return remoteProjectLinkFailure({
1546
- status: "error",
1547
- alias,
1548
- baseUrl,
1549
- repoSlug,
1550
- message: `Could not prepare remote checkout for ${repoSlug} on ${alias}: ${error instanceof Error ? error.message : String(error)}`
1551
- });
1552
- }
1553
- if (prepareResponse.status === 401 || prepareResponse.status === 403) {
1554
- return remoteProjectLinkFailure({
1555
- status: "auth_required",
1556
- alias,
1557
- baseUrl,
1558
- repoSlug,
1559
- statusCode: prepareResponse.status,
1560
- message: `Remote server ${alias} requires authentication before preparing ${repoSlug}.`
1561
- });
1562
- }
1563
- if (!prepareResponse.ok) {
1564
- return remoteProjectLinkFailure({
1565
- status: "error",
1566
- alias,
1567
- baseUrl,
1568
- repoSlug,
1569
- statusCode: prepareResponse.status,
1570
- message: `Remote checkout prepare failed for ${repoSlug} (${prepareResponse.status}): ${payloadError(prepareResponse.payload, prepareResponse.text || "prepare-checkout failed")}`,
1571
- skippedCandidates
1572
- });
1573
- }
1574
- const preparedPath = checkoutPathFromPreparePayload(prepareResponse.payload);
1575
- if (!preparedPath) {
1576
- return remoteProjectLinkFailure({
1577
- status: "invalid_root",
1578
- alias,
1579
- baseUrl,
1580
- repoSlug,
1581
- message: `Remote checkout prepare for ${repoSlug} did not return a checkout.path.`,
1582
- skippedCandidates
1583
- });
1584
- }
1585
- return validateAndPersistRemoteRoot({ projectRoot, alias, baseUrl, authToken, repoSlug, candidate: preparedPath, source: "prepare", prepared: true });
1586
- }
1587
- async function repairRemoteProjectRootLink(context, options = {}) {
1588
- const resolution = await ensureRemoteProjectRootLink(context.projectRoot, { mode: options.mode ?? "prepare-if-missing", repoSlug: options.repoSlug });
1589
- if (!resolution.ok)
1590
- throw new CliError(resolution.message, 1, { hint: resolution.hint });
1591
- return resolution;
1138
+ function readLocalConnectionFallbackToken(projectRoot) {
1139
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
1592
1140
  }
1593
1141
  async function ensureServerForCli(projectRoot) {
1594
1142
  try {
@@ -1596,12 +1144,12 @@ async function ensureServerForCli(projectRoot) {
1596
1144
  if (selected?.connection.kind === "remote") {
1597
1145
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
1598
1146
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
1599
- const link = await ensureRemoteProjectRootLink(projectRoot, { mode: "backfill-only", authToken });
1147
+ const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
1600
1148
  return {
1601
1149
  baseUrl: selected.connection.baseUrl,
1602
1150
  authToken,
1603
1151
  connectionKind: "remote",
1604
- serverProjectRoot: link.ok ? link.serverProjectRoot ?? null : null
1152
+ serverProjectRoot
1605
1153
  };
1606
1154
  }
1607
1155
  reportServerPhase("Starting local Rig server\u2026");
@@ -1619,6 +1167,29 @@ async function ensureServerForCli(projectRoot) {
1619
1167
  throw error;
1620
1168
  }
1621
1169
  }
1170
+ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
1171
+ const repo = readRepoConnection(projectRoot);
1172
+ const slug = repo?.project?.trim();
1173
+ if (!slug)
1174
+ return null;
1175
+ try {
1176
+ const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
1177
+ headers: mergeHeaders(undefined, authToken)
1178
+ });
1179
+ if (!response.ok)
1180
+ return null;
1181
+ const payload = await response.json();
1182
+ const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
1183
+ const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
1184
+ const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
1185
+ const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
1186
+ if (path)
1187
+ writeRepoServerProjectRoot(projectRoot, path);
1188
+ return path;
1189
+ } catch {
1190
+ return null;
1191
+ }
1192
+ }
1622
1193
  function appendTaskFilterParams(url, filters) {
1623
1194
  if (filters.assignee)
1624
1195
  url.searchParams.set("assignee", filters.assignee);
@@ -1629,23 +1200,10 @@ function appendTaskFilterParams(url, filters) {
1629
1200
  if (filters.limit !== undefined)
1630
1201
  url.searchParams.set("limit", String(filters.limit));
1631
1202
  }
1632
- function mergeCookie(existing, name, value) {
1633
- const encoded = `${name}=${encodeURIComponent(value)}`;
1634
- if (!existing?.trim())
1635
- return encoded;
1636
- const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
1637
- return [...parts, encoded].join("; ");
1638
- }
1639
- function queryAuthFallbackEnabled(env = process.env) {
1640
- return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
1641
- }
1642
1203
  function mergeHeaders(headers, authToken) {
1643
1204
  const merged = new Headers(headers);
1644
1205
  if (authToken) {
1645
- const bearer = `Bearer ${authToken}`;
1646
- merged.set("authorization", bearer);
1647
- merged.set("x-auth", bearer);
1648
- merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
1206
+ merged.set("authorization", `Bearer ${authToken}`);
1649
1207
  }
1650
1208
  return merged;
1651
1209
  }
@@ -1705,41 +1263,15 @@ async function buildServerFailureContext(projectRoot, server) {
1705
1263
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
1706
1264
  };
1707
1265
  }
1708
- function isLoopbackRemoteBaseUrl(baseUrl) {
1709
- try {
1710
- const host = new URL(baseUrl).hostname.toLowerCase();
1711
- return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
1712
- } catch {
1713
- return false;
1714
- }
1715
- }
1716
- function canUseRemoteWithoutProjectRoot(pathname) {
1717
- 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/");
1718
- }
1719
1266
  async function requestServerJson(context, pathname, init = {}) {
1720
1267
  const server = await ensureServerForCli(context.projectRoot);
1721
- const requestUrl = new URL(`${server.baseUrl}${pathname}`);
1722
- let scopedServerProjectRoot = server.serverProjectRoot;
1723
- if (server.connectionKind === "remote" && !scopedServerProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
1724
- const link = await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only", authToken: server.authToken });
1725
- if (link.ok && link.serverProjectRoot) {
1726
- scopedServerProjectRoot = link.serverProjectRoot;
1727
- } else {
1728
- const repo = readRepoConnection(context.projectRoot);
1729
- const target = link.alias && link.baseUrl ? `${link.alias} (${link.baseUrl})` : server.baseUrl;
1730
- throw new CliError(`Remote server ${target} is selected for ${link.repoSlug ?? repo?.project ?? "this repo"}, but this checkout has no server-host project root link. ${link.message}`, 1, { hint: link.hint });
1731
- }
1732
- }
1733
1268
  const headers = mergeHeaders(init.headers, server.authToken);
1734
- if (scopedServerProjectRoot)
1735
- headers.set("x-rig-project-root", scopedServerProjectRoot);
1736
- if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
1737
- requestUrl.searchParams.set("rt", server.authToken);
1738
- }
1269
+ if (server.serverProjectRoot)
1270
+ headers.set("x-rig-project-root", server.serverProjectRoot);
1739
1271
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
1740
1272
  let response;
1741
1273
  try {
1742
- response = await fetch(requestUrl, {
1274
+ response = await fetch(`${server.baseUrl}${pathname}`, {
1743
1275
  ...init,
1744
1276
  headers
1745
1277
  });
@@ -1801,26 +1333,11 @@ async function getGitHubAuthStatusViaServer(context) {
1801
1333
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
1802
1334
  }
1803
1335
  async function postGitHubTokenViaServer(context, token, options = {}) {
1804
- const server = await ensureServerForCli(context.projectRoot);
1805
- const requestUrl = new URL(`${server.baseUrl}/api/github/auth/token`);
1806
- reportServerPhase("POST /api/github/auth/token\u2026");
1807
- let response;
1808
- try {
1809
- response = await fetch(requestUrl, {
1810
- method: "POST",
1811
- headers: { "content-type": "application/json" },
1812
- body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot ?? server.serverProjectRoot ?? undefined })
1813
- });
1814
- } catch (error) {
1815
- const failure = await buildServerFailureContext(context.projectRoot, server);
1816
- throw new CliError(`Rig server auth bootstrap failed: ${error instanceof Error ? error.message : String(error)}
1817
- ${failure.contextLine}`, 1, { hint: failure.hint });
1818
- }
1819
- const payload = await response.json().catch(() => null);
1820
- if (!response.ok) {
1821
- const detail = payload && typeof payload === "object" && !Array.isArray(payload) ? String(payload.error ?? JSON.stringify(payload)) : `HTTP ${response.status}`;
1822
- 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`." });
1823
- }
1336
+ const payload = await requestServerJson(context, "/api/github/auth/token", {
1337
+ method: "POST",
1338
+ headers: { "content-type": "application/json" },
1339
+ body: JSON.stringify({ token, selectedRepo: options.selectedRepo, projectRoot: options.projectRoot })
1340
+ });
1824
1341
  return payload && typeof payload === "object" && !Array.isArray(payload) ? payload : {};
1825
1342
  }
1826
1343
  async function prepareRemoteCheckoutViaServer(context, input) {
@@ -2098,14 +1615,6 @@ function permissionAllowsPr(payload) {
2098
1615
  function isNotFoundError(error) {
2099
1616
  return /\b(404|not found)\b/i.test(message(error));
2100
1617
  }
2101
- function isLoopbackBaseUrl(baseUrl) {
2102
- try {
2103
- const host = new URL(baseUrl).hostname.toLowerCase();
2104
- return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
2105
- } catch {
2106
- return false;
2107
- }
2108
- }
2109
1618
  function projectCheckoutReady(payload) {
2110
1619
  if (!payload || typeof payload !== "object" || Array.isArray(payload))
2111
1620
  return null;
@@ -2159,38 +1668,25 @@ async function runFastTaskRunPreflight(context, options = {}) {
2159
1668
  }
2160
1669
  }
2161
1670
  const repo = readRepoConnection(context.projectRoot);
2162
- const remoteWithoutProjectLink = selectedServer?.connectionKind === "remote" && !repo?.project;
2163
- let remoteRootBlocked = false;
2164
- 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 server repair-link --repo owner/repo` or `rig init --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>`."));
2165
- if (selectedServer?.connectionKind === "remote" && repo?.project && !selectedServer.serverProjectRoot) {
2166
- const link = await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only", authToken: selectedServer.authToken });
2167
- const loopbackDevRemote = !selectedServer.authToken && isLoopbackBaseUrl(selectedServer.baseUrl);
2168
- checks.push(preflightCheck("remote-project-root-link", "remote server checkout/root linked", link.ok ? "pass" : loopbackDevRemote ? "warn" : "fail", link.ok ? `${link.repoSlug} -> ${link.serverProjectRoot}` : link.message, link.ok ? undefined : loopbackDevRemote ? "Loopback development remotes may continue without x-rig-project-root; production remotes must run `rig server repair-link`." : link.hint));
2169
- remoteRootBlocked = !link.ok && !loopbackDevRemote;
2170
- }
1671
+ 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>`."));
2171
1672
  try {
2172
1673
  const auth = await request("/api/github/auth/status");
2173
1674
  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>`."));
2174
1675
  } catch (error) {
2175
1676
  checks.push(preflightCheck("github-auth", "GitHub auth valid", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix GitHub auth on the selected Rig server."));
2176
1677
  }
2177
- if (!remoteRootBlocked) {
2178
- try {
2179
- const projection = await request("/api/workspace/task-projection");
2180
- checks.push(preflightCheck("task-projection", "task projection ready", "pass", JSON.stringify(projection).slice(0, 120)));
2181
- } catch (error) {
2182
- checks.push(preflightCheck("task-projection", "task projection ready", "warn", message(error), "Refresh task projection with `rig task list` before launching."));
2183
- }
2184
- try {
2185
- const permissions = await request("/api/github/repo/permissions");
2186
- const allowed = permissionAllowsPr(permissions);
2187
- checks.push(allowed === false ? preflightCheck("github-repo-permissions", "GitHub PR permissions", "fail", JSON.stringify(permissions).slice(0, 120), "Grant the selected GitHub token permission to push branches and open PRs.") : preflightCheck("github-repo-permissions", "GitHub PR permissions", allowed === true ? "pass" : "warn", JSON.stringify(permissions).slice(0, 120), "Confirm the selected token can push branches and open PRs."));
2188
- } catch (error) {
2189
- checks.push(preflightCheck("github-repo-permissions", "GitHub PR permissions", "warn", message(error), "Ensure the selected token can push branches and open PRs."));
2190
- }
2191
- } else {
2192
- checks.push(preflightCheck("task-projection", "task projection ready", "warn", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
2193
- checks.push(preflightCheck("github-repo-permissions", "GitHub PR permissions", "warn", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
1678
+ try {
1679
+ const projection = await request("/api/workspace/task-projection");
1680
+ checks.push(preflightCheck("task-projection", "task projection ready", "pass", JSON.stringify(projection).slice(0, 120)));
1681
+ } catch (error) {
1682
+ checks.push(preflightCheck("task-projection", "task projection ready", "warn", message(error), "Refresh task projection with `rig task list` before launching."));
1683
+ }
1684
+ try {
1685
+ const permissions = await request("/api/github/repo/permissions");
1686
+ const allowed = permissionAllowsPr(permissions);
1687
+ checks.push(allowed === false ? preflightCheck("github-repo-permissions", "GitHub PR permissions", "fail", JSON.stringify(permissions).slice(0, 120), "Grant the selected GitHub token permission to push branches and open PRs.") : preflightCheck("github-repo-permissions", "GitHub PR permissions", allowed === true ? "pass" : "warn", JSON.stringify(permissions).slice(0, 120), "Confirm the selected token can push branches and open PRs."));
1688
+ } catch (error) {
1689
+ checks.push(preflightCheck("github-repo-permissions", "GitHub PR permissions", "warn", message(error), "Ensure the selected token can push branches and open PRs."));
2194
1690
  }
2195
1691
  if (repo?.project) {
2196
1692
  try {
@@ -2202,24 +1698,19 @@ async function runFastTaskRunPreflight(context, options = {}) {
2202
1698
  }
2203
1699
  }
2204
1700
  if (taskId) {
2205
- if (!remoteRootBlocked) {
2206
- try {
2207
- const tasks = await request(`/api/workspace/tasks?limit=200&refresh=1`);
2208
- const found = Array.isArray(tasks) && tasks.some((task) => taskMatchesId(task, taskId));
2209
- checks.push(found ? preflightCheck("issue", "task/issue accessible", "pass", taskId) : preflightCheck("issue", "task/issue accessible", legacyServerCompatibility ? "warn" : "fail", taskId, "Confirm the issue exists and matches the configured task filters."));
2210
- } catch (error) {
2211
- checks.push(preflightCheck("issue", "task/issue accessible", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix the task source before launching a run."));
2212
- }
2213
- try {
2214
- const runs = await request("/api/runs?limit=200");
2215
- const duplicate = activeDuplicateRun(runs, taskId);
2216
- checks.push(duplicate ? preflightCheck("duplicate-active-run", "one active run per task", "fail", String(duplicate.runId ?? taskId), "Attach to or stop the existing run before starting another one for this task.") : preflightCheck("duplicate-active-run", "one active run per task", "pass", taskId));
2217
- } catch (error) {
2218
- checks.push(preflightCheck("duplicate-active-run", "one active run per task", "warn", message(error), "Could not list active runs; the server will still reject conflicting runs if configured."));
2219
- }
2220
- } else {
2221
- checks.push(preflightCheck("issue", "task/issue accessible", "fail", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
2222
- checks.push(preflightCheck("duplicate-active-run", "one active run per task", "warn", "skipped until remote project-root link is repaired", "Run `rig server repair-link`, then retry."));
1701
+ try {
1702
+ const tasks = await request(`/api/workspace/tasks?limit=200&refresh=1`);
1703
+ const found = Array.isArray(tasks) && tasks.some((task) => taskMatchesId(task, taskId));
1704
+ checks.push(found ? preflightCheck("issue", "task/issue accessible", "pass", taskId) : preflightCheck("issue", "task/issue accessible", legacyServerCompatibility ? "warn" : "fail", taskId, "Confirm the issue exists and matches the configured task filters."));
1705
+ } catch (error) {
1706
+ checks.push(preflightCheck("issue", "task/issue accessible", legacyServerCompatibility ? "warn" : "fail", message(error), "Fix the task source before launching a run."));
1707
+ }
1708
+ try {
1709
+ const runs = await request("/api/runs?limit=200");
1710
+ const duplicate = activeDuplicateRun(runs, taskId);
1711
+ checks.push(duplicate ? preflightCheck("duplicate-active-run", "one active run per task", "fail", String(duplicate.runId ?? taskId), "Attach to or stop the existing run before starting another one for this task.") : preflightCheck("duplicate-active-run", "one active run per task", "pass", taskId));
1712
+ } catch (error) {
1713
+ checks.push(preflightCheck("duplicate-active-run", "one active run per task", "warn", message(error), "Could not list active runs; the server will still reject conflicting runs if configured."));
2223
1714
  }
2224
1715
  }
2225
1716
  if ((options.runtimeAdapter ?? "pi") === "pi") {
@@ -2288,8 +1779,18 @@ import {
2288
1779
  readJsonlFile as readJsonlFile2,
2289
1780
  writeAuthorityRunRecord
2290
1781
  } from "@rig/runtime/control-plane/authority-files";
2291
- function normalizeRuntimeAdapter(_value) {
2292
- return "pi";
1782
+ function normalizeRuntimeAdapter(value) {
1783
+ const normalized = value?.trim().toLowerCase();
1784
+ if (!normalized) {
1785
+ return "pi";
1786
+ }
1787
+ if (normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "gpt-codex") {
1788
+ return "codex";
1789
+ }
1790
+ if (normalized === "pi" || normalized === "rig-pi" || normalized === "@rig/pi") {
1791
+ return "pi";
1792
+ }
1793
+ return "claude-code";
2293
1794
  }
2294
1795
  function readLatestBeadRecord(projectRoot, taskId) {
2295
1796
  const issuesPath = resolve12(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
@@ -2703,19 +2204,16 @@ function formatConnectionList(connections) {
2703
2204
  return [formatSection("Rig servers", `${rows.length} available`), `${pc3.bold(pad("ALIAS", aliasWidth))} ${pc3.bold("KIND")} ${pc3.bold("TARGET")}`, ...lines, "", ...formatNextSteps(["Select one: `rig server use <alias|local>`"])].join(`
2704
2205
  `);
2705
2206
  }
2706
- function formatConnectionStatus(selected, connections, repo, remoteProjectLink) {
2207
+ function formatConnectionStatus(selected, connections) {
2707
2208
  const connection = selected === "local" ? { kind: "local", mode: "auto" } : connections[selected];
2708
2209
  const target = !connection ? "not configured" : connection.kind === "remote" ? connection.baseUrl : "local";
2709
- const rootLabel = remoteProjectLink ? remoteProjectLink.ok ? `ready \xB7 ${remoteProjectLink.serverProjectRoot ?? repo?.serverProjectRoot ?? "linked"}` : `${remoteProjectLink.status ?? "needs repair"} \xB7 ${remoteProjectLink.hint ?? remoteProjectLink.message ?? "run rig server repair-link"}` : repo?.serverProjectRoot ? repo.serverProjectRoot : "not required";
2710
2210
  return [
2711
2211
  formatSection("Rig server", "selected for this repo"),
2712
2212
  `${themeFaint("\u2502")} ${themeDim("selected ")} ${pc3.bold(selected)}`,
2713
2213
  `${themeFaint("\u2502")} ${themeDim("kind ")} ${formatStatusPill(connection?.kind ?? "unknown")}`,
2714
2214
  `${themeFaint("\u2502")} ${themeDim("target ")} ${target ?? "not configured"}`,
2715
- ...repo?.project ? [`${themeFaint("\u2502")} ${themeDim("project ")} ${repo.project}`] : [],
2716
- ...connection?.kind === "remote" ? [`${themeFaint("\u2502")} ${themeDim("root ")} ${rootLabel}`] : [],
2717
2215
  "",
2718
- ...formatNextSteps(remoteProjectLink && !remoteProjectLink.ok ? ["Repair remote link: `rig server repair-link`", "Authenticate first if needed: `rig github auth import-gh`"] : ["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
2216
+ ...formatNextSteps(["Change: `rig server use <alias|local>`", "List saved servers: `rig server list`"])
2719
2217
  ].join(`
2720
2218
  `);
2721
2219
  }
@@ -3214,7 +2712,7 @@ var init__operator_surface = __esm(() => {
3214
2712
  });
3215
2713
 
3216
2714
  // packages/cli/src/commands/_pi-frontend.ts
3217
- import { existsSync as existsSync15, mkdirSync as mkdirSync11, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync5, writeFileSync as writeFileSync8 } from "fs";
2715
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9, mkdtempSync, readFileSync as readFileSync10, rmSync as rmSync5, writeFileSync as writeFileSync6 } from "fs";
3218
2716
  import { homedir as homedir6, tmpdir } from "os";
3219
2717
  import { join as join3 } from "path";
3220
2718
  import { main as runPiMain } from "@earendil-works/pi-coding-agent";
@@ -3246,27 +2744,10 @@ function buildOperatorPiEnv(input) {
3246
2744
  ...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
3247
2745
  };
3248
2746
  }
3249
- function shouldRequireOperatorTranscript(status) {
3250
- return typeof status === "string" && TERMINAL_RUN_STATUSES.has(status.trim().toLowerCase());
3251
- }
3252
- function missingOperatorTranscriptMessage(runId, status) {
3253
- const shortRun = runId.trim().slice(0, 8) || "unknown";
3254
- const statusText = typeof status === "string" && status.trim() ? status.trim() : "terminal";
3255
- return `Run ${shortRun} is ${statusText}, but no worker Pi session transcript is recorded for this run. It likely failed before Pi started or predates full-session capture. Use \`rig run show ${runId}\` and \`rig run logs ${runId}\` for the lifecycle details.`;
3256
- }
3257
- function statusFromRunDetails(run) {
3258
- if (!run || typeof run !== "object" || Array.isArray(run))
3259
- return;
3260
- const record = run;
3261
- if (typeof record.status === "string")
3262
- return record.status;
3263
- const nested = record.run;
3264
- return nested && typeof nested === "object" && !Array.isArray(nested) ? nested.status : undefined;
3265
- }
3266
2747
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
3267
2748
  const server = await ensureServerForCli(context.projectRoot);
3268
2749
  const localCwd = join3(homedir6(), ".rig", "drones", runId.slice(0, 8));
3269
- mkdirSync11(localCwd, { recursive: true });
2750
+ mkdirSync9(localCwd, { recursive: true });
3270
2751
  trustDroneCwd(localCwd);
3271
2752
  installRigPiTheme();
3272
2753
  let sessionFileArg = [];
@@ -3288,28 +2769,21 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
3288
2769
  return line;
3289
2770
  }).join(`
3290
2771
  `);
3291
- writeFileSync8(localSessionPath, content);
2772
+ writeFileSync6(localSessionPath, content);
3292
2773
  sessionFileArg = ["--session", localSessionPath];
3293
2774
  }
3294
2775
  } catch {}
3295
- if (sessionFileArg.length === 0) {
3296
- const run = await getRunDetailsViaServer(context, runId).catch(() => null);
3297
- const status = statusFromRunDetails(run);
3298
- if (shouldRequireOperatorTranscript(status)) {
3299
- throw new OperatorTranscriptUnavailableError(missingOperatorTranscriptMessage(runId, status));
3300
- }
3301
- }
3302
2776
  return { server, sessionFileArg };
3303
2777
  }
3304
2778
  function trustDroneCwd(localCwd) {
3305
2779
  try {
3306
2780
  const agentDir = join3(homedir6(), ".pi", "agent");
3307
- mkdirSync11(agentDir, { recursive: true });
2781
+ mkdirSync9(agentDir, { recursive: true });
3308
2782
  const trustPath = join3(agentDir, "trust.json");
3309
2783
  const store = existsSync15(trustPath) ? JSON.parse(readFileSync10(trustPath, "utf8")) : {};
3310
2784
  if (store[localCwd] !== true) {
3311
2785
  store[localCwd] = true;
3312
- writeFileSync8(trustPath, `${JSON.stringify(store, null, "\t")}
2786
+ writeFileSync6(trustPath, `${JSON.stringify(store, null, "\t")}
3313
2787
  `);
3314
2788
  }
3315
2789
  } catch {}
@@ -3317,38 +2791,15 @@ function trustDroneCwd(localCwd) {
3317
2791
  function installRigPiTheme() {
3318
2792
  try {
3319
2793
  const themesDir = join3(homedir6(), ".pi", "agent", "themes");
3320
- mkdirSync11(themesDir, { recursive: true });
2794
+ mkdirSync9(themesDir, { recursive: true });
3321
2795
  const themePath = join3(themesDir, "rig.json");
3322
2796
  const next = `${JSON.stringify(RIG_PI_THEME, null, "\t")}
3323
2797
  `;
3324
2798
  if (!existsSync15(themePath) || readFileSync10(themePath, "utf8") !== next) {
3325
- writeFileSync8(themePath, next);
2799
+ writeFileSync6(themePath, next);
3326
2800
  }
3327
2801
  } catch {}
3328
2802
  }
3329
- async function runWithProcessExitGuard(body) {
3330
- const realExit = process.exit;
3331
- let exitCode = 0;
3332
- let signalQuit = () => {};
3333
- const quit = new Promise((resolve23) => {
3334
- signalQuit = resolve23;
3335
- });
3336
- const guardedExit = (code) => {
3337
- exitCode = typeof code === "number" ? code : 0;
3338
- signalQuit();
3339
- return;
3340
- };
3341
- process.exit = guardedExit;
3342
- try {
3343
- await Promise.race([Promise.resolve().then(body), quit]);
3344
- } finally {
3345
- process.exit = realExit;
3346
- }
3347
- return exitCode;
3348
- }
3349
- function runPiMainReturningOnQuit(args, options) {
3350
- return runWithProcessExitGuard(() => runPiMain(args, options));
3351
- }
3352
2803
  async function attachRunBundledPiFrontend(context, input) {
3353
2804
  const tempSessionDir = mkdtempSync(join3(tmpdir(), "rig-pi-frontend-sessions-"));
3354
2805
  const { server, sessionFileArg } = await withSpinner(`Opening Pi console for run ${input.runId}\u2026`, () => prepareOperatorConsole(context, input.runId, tempSessionDir), { outputMode: context.outputMode });
@@ -3364,20 +2815,15 @@ async function attachRunBundledPiFrontend(context, input) {
3364
2815
  };
3365
2816
  let detached = false;
3366
2817
  try {
3367
- const piArgs = [
3368
- "--offline",
2818
+ await runPiMain([
3369
2819
  "--no-extensions",
3370
2820
  "--no-skills",
3371
2821
  "--no-prompt-templates",
3372
2822
  "--no-context-files",
3373
2823
  ...sessionFileArg
3374
- ];
3375
- const piOptions = { extensionFactories: [piRigExtensionFactory] };
3376
- if (input.returnOnQuit) {
3377
- await runPiMainReturningOnQuit(piArgs, piOptions);
3378
- } else {
3379
- await runPiMain(piArgs, piOptions);
3380
- }
2824
+ ], {
2825
+ extensionFactories: [piRigExtensionFactory]
2826
+ });
3381
2827
  detached = true;
3382
2828
  } finally {
3383
2829
  restoreEnv();
@@ -3397,17 +2843,10 @@ async function attachRunBundledPiFrontend(context, input) {
3397
2843
  rendered: "stock Pi operator console with the pi-rig extension"
3398
2844
  };
3399
2845
  }
3400
- var TERMINAL_RUN_STATUSES, OperatorTranscriptUnavailableError, RIG_PI_THEME;
2846
+ var RIG_PI_THEME;
3401
2847
  var init__pi_frontend = __esm(() => {
3402
2848
  init__server_client();
3403
2849
  init__async_ui();
3404
- TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
3405
- OperatorTranscriptUnavailableError = class OperatorTranscriptUnavailableError extends Error {
3406
- constructor(message2) {
3407
- super(message2);
3408
- this.name = "OperatorTranscriptUnavailableError";
3409
- }
3410
- };
3411
2850
  RIG_PI_THEME = {
3412
2851
  $schema: "https://raw.githubusercontent.com/earendil-works/pi/main/packages/coding-agent/src/modes/interactive/theme/theme-schema.json",
3413
2852
  name: "rig",
@@ -3562,7 +3001,7 @@ async function attachRunOperatorView(context, input) {
3562
3001
  }
3563
3002
  const pollMs = Math.max(250, Math.trunc(input.pollMs ?? 2000));
3564
3003
  let timelineCursor = snapshot.timelineCursor;
3565
- while (!detached && !TERMINAL_RUN_STATUSES2.has(runStatusFromPayload(snapshot.run))) {
3004
+ while (!detached && !TERMINAL_RUN_STATUSES.has(runStatusFromPayload(snapshot.run))) {
3566
3005
  await Bun.sleep(pollMs);
3567
3006
  snapshot = await readOperatorSnapshot(context, input.runId, { timelineCursor });
3568
3007
  timelineCursor = snapshot.timelineCursor;
@@ -3574,13 +3013,13 @@ async function attachRunOperatorView(context, input) {
3574
3013
  }
3575
3014
  return { ...snapshot, steered, detached };
3576
3015
  }
3577
- var TERMINAL_RUN_STATUSES2;
3016
+ var TERMINAL_RUN_STATUSES;
3578
3017
  var init__operator_view = __esm(() => {
3579
3018
  init__server_client();
3580
3019
  init__operator_surface();
3581
3020
  init__pi_frontend();
3582
3021
  init__async_ui();
3583
- TERMINAL_RUN_STATUSES2 = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
3022
+ TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
3584
3023
  });
3585
3024
 
3586
3025
  // packages/cli/src/commands/_help-catalog.ts
@@ -3750,13 +3189,12 @@ var init__help_catalog = __esm(() => {
3750
3189
  {
3751
3190
  name: "server",
3752
3191
  summary: "Choose, inspect, and start the Rig server that owns tasks and runs.",
3753
- usage: ["rig server <status|list|add|use|repair-link|start> [options]"],
3192
+ usage: ["rig server <status|list|add|use|start> [options]"],
3754
3193
  commands: [
3755
- { command: "status", description: "Show the selected server and remote project-root link for this repo.", primary: true },
3194
+ { command: "status", description: "Show the selected server for this repo.", primary: true },
3756
3195
  { command: "use local", description: "Switch this repo to the local Rig server.", primary: true },
3757
3196
  { command: "add <alias> <url>", description: "Save a remote Rig server URL.", primary: true },
3758
3197
  { command: "use <alias>", description: "Select a saved remote server alias.", primary: true },
3759
- { command: "repair-link [--prepare|--backfill-only] [--repo owner/repo]", description: "Backfill or prepare the selected remote's server-host checkout link.", primary: true },
3760
3198
  { command: "list", description: "List saved local/remote server aliases.", primary: true },
3761
3199
  { command: "start [--host <host>] [--port <n>]", description: "Start a local rig-server process." }
3762
3200
  ],
@@ -3764,7 +3202,6 @@ var init__help_catalog = __esm(() => {
3764
3202
  "rig server status",
3765
3203
  "rig server add prod https://where.rig-does.work",
3766
3204
  "rig server use prod",
3767
- "rig server repair-link --repo owner/repo",
3768
3205
  "rig server use local",
3769
3206
  "rig server start --port 3773"
3770
3207
  ],
@@ -3939,62 +3376,30 @@ var init__help_catalog = __esm(() => {
3939
3376
  }
3940
3377
  ];
3941
3378
  ADVANCED_GROUPS = [
3942
- {
3943
- name: "setup",
3944
- summary: "Bootstrap/check local setup.",
3945
- usage: ["rig setup <bootstrap|check|preflight>"],
3946
- commands: [
3947
- { command: "bootstrap", description: "Bootstrap local setup dependencies.", primary: true },
3948
- { command: "check", description: "Check local setup state (toolchain, deps, config).", primary: true },
3949
- { command: "preflight", description: "Run preflight checks before a run.", primary: true }
3950
- ]
3951
- },
3952
- {
3953
- name: "profile",
3954
- summary: "Runtime profile/model defaults.",
3955
- usage: ["rig profile <show|set>"],
3956
- commands: [
3957
- { command: "show", description: "Show the active execution profile.", primary: true },
3958
- { command: "set [--model <model>] [--runtime <runtime>] [--plugin <plugin>]", description: "Set model/runtime/plugin profile defaults.", primary: true }
3959
- ]
3960
- },
3379
+ { name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
3380
+ { name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
3961
3381
  {
3962
3382
  name: "review",
3963
3383
  summary: "Inspect or change completion review gate policy.",
3964
3384
  usage: ["rig review <show|set>"],
3965
3385
  commands: [
3966
3386
  { command: "show", description: "Show current review gate settings." },
3967
- { command: "set <off|advisory|required> [--provider <provider>]", description: "Change review strictness/provider (e.g. --provider greptile)." }
3387
+ { command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider." }
3968
3388
  ],
3969
3389
  examples: ["rig review show", "rig review set required --provider greptile"],
3970
3390
  next: ["Use `rig inbox approvals` for blocked run handoffs."]
3971
3391
  },
3972
3392
  {
3973
3393
  name: "browser",
3974
- summary: "Browser workstation actions for browser-required tasks: launch, check, CDP probe, profile reset, and app-specific smokes.",
3975
- usage: ["rig browser <help|explain|demo|hp-next|cdp-probe|profile-persistence|profile-lock-check|smoke-test> [options]"],
3394
+ summary: "Browser/app diagnostics for browser-required tasks.",
3395
+ usage: ["rig browser <help|explain|demo|app|hp-next> [options]"],
3976
3396
  commands: [
3977
- { command: "help", description: "Rich browser command help (canonical: `rig browser help`).", primary: true },
3978
- { command: "explain", description: "Explain the browser-required task contract and runtime helper commands.", primary: true },
3979
- { command: "demo [--port <n>] [--profile <name>] [--state-dir <path>] [--target-url <url>] [--keep-open] [--no-build]", description: "Run a guided real browser/agent demo flow.", primary: true },
3980
- { command: "hp-next dev", description: "Start hp-next Rig Browser in dev/watch mode.", primary: true },
3981
- { command: "hp-next start", description: "Build/start the hp-next browser workstation without watch mode.", primary: true },
3982
- { command: "hp-next check", description: "Validate the hp-next CDP endpoint on the configured port.", primary: true },
3983
- { command: "hp-next e2e", description: "Run hp-next browser e2e smoke checks through Rig Browser.", primary: true },
3984
- { command: "hp-next reset", description: "Reset the hp-next browser profile when stale browser state is suspected.", primary: true },
3985
- { command: "cdp-probe", description: "Run an isolated CDP attach/evaluate/layout probe." },
3986
- { command: "profile-persistence", description: "Verify a named browser profile persists browser state." },
3987
- { command: "profile-lock-check", description: "Verify concurrent launches reject the same profile." },
3988
- { command: "smoke-test", description: "Run the browser package smoke test." }
3989
- ],
3990
- examples: [
3991
- "rig browser help",
3992
- "rig browser hp-next check",
3993
- "rig browser hp-next e2e",
3994
- "rig browser cdp-probe",
3995
- "rig browser profile-lock-check"
3996
- ],
3997
- next: ["Inside a task run, use rig-browser-launch, rig-browser-check, and rig-browser-attach-info from the worker PATH."]
3397
+ { command: "help", description: "Rich browser command help (canonical: `rig browser help`)." },
3398
+ { command: "explain", description: "Explain the browser-required task contract." },
3399
+ { command: "demo", description: "Run browser demo flows against a local page." },
3400
+ { command: "app", description: "Launch the Rig Browser workstation app." },
3401
+ { command: "hp-next <dev|check|e2e|reset>", description: "Drive the hp-next browser test harness." }
3402
+ ]
3998
3403
  },
3999
3404
  {
4000
3405
  name: "pi",
@@ -4009,60 +3414,12 @@ var init__help_catalog = __esm(() => {
4009
3414
  examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
4010
3415
  next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
4011
3416
  },
4012
- {
4013
- name: "queue",
4014
- summary: "Run task queues locally.",
4015
- usage: ["rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]"],
4016
- commands: [
4017
- { command: "run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]", description: "Process queue work: drain matching tasks with N workers, optional per-task action and isolation.", primary: true }
4018
- ]
4019
- },
4020
- {
4021
- name: "agent",
4022
- summary: "Runtime agent workspace helpers.",
4023
- usage: ["rig agent <list|prepare|run|cleanup>"],
4024
- commands: [
4025
- { command: "list", description: "List prepared agent runtimes.", primary: true },
4026
- { command: "prepare [--id <id>] [--mode <mode>] [--task <task>]", description: "Prepare an isolated agent runtime workspace.", primary: true },
4027
- { command: "run [--id <id>] [--mode <mode>] [--task <task>] [--skip-project-sync]", description: "Prepare (if needed) and run an agent in its workspace.", primary: true },
4028
- { command: "cleanup [--all] [--id <id>]", description: "Remove prepared agent workspaces.", primary: true }
4029
- ]
4030
- },
3417
+ { name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
3418
+ { name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
4031
3419
  { name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
4032
- {
4033
- name: "dist",
4034
- summary: "Build/install packaged Rig CLI.",
4035
- usage: ["rig dist <build|install|doctor|rebuild-agent>"],
4036
- commands: [
4037
- { command: "build [--output-dir <dir>]", description: "Build the distributable Rig CLI.", primary: true },
4038
- { command: "install [--scope <scope>] [--path <path>]", description: "Install the built CLI to a scope/path.", primary: true },
4039
- { command: "doctor", description: "Diagnose the dist toolchain and install state.", primary: true },
4040
- { command: "rebuild-agent", description: "Rebuild the agent runtime image, pruning stale images.", primary: true }
4041
- ]
4042
- },
3420
+ { name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
4043
3421
  { name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
4044
- {
4045
- name: "remote",
4046
- summary: "Compatibility remote orchestration controls.",
4047
- usage: ["rig remote <status|tasks|watch|pause|resume|continue|stop|refresh|add-iterations|remove-iterations|endpoint ...>"],
4048
- commands: [
4049
- { command: "status [--remote <alias>]", description: "Show the remote orchestration state.", primary: true },
4050
- { command: "tasks [--remote <alias>]", description: "List the remote's tracked tasks.", primary: true },
4051
- { command: "watch [--remote <alias>] [--seconds <n>] [--event <type>]", description: "Stream remote orchestration events.", primary: true },
4052
- { command: "pause [--remote <alias>]", description: "Pause the running remote orchestration.", primary: true },
4053
- { command: "resume [--remote <alias>] [--max-workers <n>] [--max-iterations <n>] [--direct-merge]", description: "Resume the remote with optional tuning.", primary: true },
4054
- { command: "continue [--remote <alias>]", description: "Continue a paused remote orchestration.", primary: true },
4055
- { command: "stop [--remote <alias>]", description: "Stop the remote orchestration.", primary: true },
4056
- { command: "refresh [--remote <alias>]", description: "Refresh remote state.", primary: true },
4057
- { command: "add-iterations [--count <n>] [--remote <alias>]", description: "Grant the remote more iterations.", primary: true },
4058
- { command: "remove-iterations [--count <n>] [--remote <alias>]", description: "Reduce the remote's iteration budget.", primary: true },
4059
- { command: "endpoint list", description: "List configured remote endpoints.", primary: true },
4060
- { command: "endpoint add --alias <alias> --host <host> --port <n> [--token <token>]", description: "Register a remote endpoint.", primary: true },
4061
- { command: "endpoint remove --alias <alias>", description: "Remove a remote endpoint.", primary: true },
4062
- { command: "endpoint test [--alias <alias>]", description: "Test connectivity to a remote endpoint.", primary: true },
4063
- { command: "endpoint doctor", description: "Diagnose remote endpoint configuration.", primary: true }
4064
- ]
4065
- },
3422
+ { name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
4066
3423
  { name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
4067
3424
  { name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
4068
3425
  { name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
@@ -4129,7 +3486,7 @@ var init__task_picker = __esm(() => {
4129
3486
  // packages/cli/src/commands/task.ts
4130
3487
  import { readFileSync as readFileSync11 } from "fs";
4131
3488
  import { spawnSync as spawnSync3 } from "child_process";
4132
- import { resolve as resolve23 } from "path";
3489
+ import { resolve as resolve22 } from "path";
4133
3490
  import {
4134
3491
  taskArtifactDir,
4135
3492
  taskArtifacts,
@@ -4407,7 +3764,7 @@ async function executeTask(context, args, options) {
4407
3764
  const fileFlag = takeOption(rest.slice(1), "--file");
4408
3765
  let content;
4409
3766
  if (fileFlag.value) {
4410
- content = readFileSync11(resolve23(context.projectRoot, fileFlag.value), "utf-8");
3767
+ content = readFileSync11(resolve22(context.projectRoot, fileFlag.value), "utf-8");
4411
3768
  } else {
4412
3769
  content = await readStdin();
4413
3770
  }
@@ -4645,47 +4002,6 @@ var init_task = __esm(() => {
4645
4002
  init__connection_state();
4646
4003
  });
4647
4004
 
4648
- // packages/cli/src/commands/_server-events.ts
4649
- import { WsTransport } from "@rig/client";
4650
- import { RIG_WS_CHANNELS } from "@rig/contracts";
4651
- function buildRigWebSocketUrl(baseUrl, authToken) {
4652
- const url = new URL(baseUrl);
4653
- url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
4654
- if (authToken)
4655
- url.searchParams.set("token", authToken);
4656
- return url.toString();
4657
- }
4658
- async function connectRigServerEvents(projectRoot, handlers) {
4659
- const { baseUrl, authToken } = await ensureServerForCli(projectRoot);
4660
- const transport = new WsTransport(buildRigWebSocketUrl(baseUrl, authToken));
4661
- const unsubscribers = [];
4662
- if (handlers.onSnapshotInvalidated)
4663
- unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.snapshotInvalidated, handlers.onSnapshotInvalidated));
4664
- if (handlers.onRunLogAppended)
4665
- unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.runLogAppended, handlers.onRunLogAppended));
4666
- if (handlers.onEngineEvent)
4667
- unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.event, handlers.onEngineEvent));
4668
- let status = "connecting";
4669
- unsubscribers.push(transport.subscribeState((state) => {
4670
- status = state.status;
4671
- handlers.onStatus?.(state.status);
4672
- }));
4673
- return {
4674
- connected: () => status === "connected",
4675
- close: () => {
4676
- for (const unsubscribe of unsubscribers) {
4677
- try {
4678
- unsubscribe();
4679
- } catch {}
4680
- }
4681
- transport.dispose();
4682
- }
4683
- };
4684
- }
4685
- var init__server_events = __esm(() => {
4686
- init__server_client();
4687
- });
4688
-
4689
4005
  // packages/cli/src/app/board.ts
4690
4006
  var exports_board = {};
4691
4007
  __export(exports_board, {
@@ -4717,7 +4033,6 @@ function statusRank(status) {
4717
4033
  case "pending":
4718
4034
  case "preparing":
4719
4035
  case "adopted":
4720
- case "stopping":
4721
4036
  return 2;
4722
4037
  case "completed":
4723
4038
  case "merged":
@@ -4757,10 +4072,6 @@ class RunsList {
4757
4072
  selectedRun() {
4758
4073
  return this.visibleRuns()[this.selected] ?? null;
4759
4074
  }
4760
- patchRun(runId, patch) {
4761
- this.runs = this.runs.map((run) => run.runId === runId ? { ...run, ...patch } : run);
4762
- this.clampSelection();
4763
- }
4764
4075
  cycleSort() {
4765
4076
  this.sortMode = this.sortMode === "active" ? "recent" : this.sortMode === "recent" ? "status" : "active";
4766
4077
  this.clampSelection();
@@ -4983,14 +4294,6 @@ class InboxView {
4983
4294
  selectedItem() {
4984
4295
  return this.items[this.selected] ?? null;
4985
4296
  }
4986
- patchItem(requestId, summary) {
4987
- this.items = this.items.map((item) => item.requestId === requestId ? { ...item, summary } : item);
4988
- }
4989
- removeItem(requestId) {
4990
- const previousIndex = this.selected;
4991
- this.items = this.items.filter((item) => item.requestId !== requestId);
4992
- this.selected = Math.max(0, Math.min(previousIndex, Math.max(0, this.items.length - 1)));
4993
- }
4994
4297
  invalidate() {}
4995
4298
  render(width) {
4996
4299
  return this.renderLines(width).map((line) => truncateToWidth(line, Math.max(10, width - 1)));
@@ -5212,14 +4515,9 @@ async function runOperatorBoard(context, options = {}) {
5212
4515
  tui.stop();
5213
4516
  };
5214
4517
  let refreshInFlight = false;
5215
- const refresh = async (options2 = {}) => {
4518
+ const refresh = async () => {
5216
4519
  if (refreshInFlight)
5217
4520
  return;
5218
- if (!options2.quiet) {
5219
- notice = "refreshing fleet\u2026";
5220
- renderFooter();
5221
- tui.requestRender();
5222
- }
5223
4521
  if (!hasRigProject(context.projectRoot)) {
5224
4522
  list.loading = false;
5225
4523
  list.noProject = true;
@@ -5302,7 +4600,6 @@ async function runOperatorBoard(context, options = {}) {
5302
4600
  };
5303
4601
  const resolveApproval = async (item, decision) => {
5304
4602
  notice = `${decision === "approve" ? "approving" : "rejecting"} ${item.requestId.slice(0, 12)}\u2026`;
5305
- inboxView.patchItem(item.requestId, `${decision === "approve" ? "approving" : "rejecting"}\u2026 ${item.summary}`);
5306
4603
  renderFooter();
5307
4604
  tui.requestRender();
5308
4605
  try {
@@ -5311,10 +4608,8 @@ async function runOperatorBoard(context, options = {}) {
5311
4608
  headers: { "content-type": "application/json" },
5312
4609
  body: JSON.stringify({ runId: item.runId, requestId: item.requestId, decision, note: null })
5313
4610
  });
5314
- inboxView.removeItem(item.requestId);
5315
4611
  notice = `${decision === "approve" ? "approved" : "rejected"} \u2014 drone resumes`;
5316
4612
  } catch (error) {
5317
- inboxView.patchItem(item.requestId, item.summary);
5318
4613
  notice = `resolve failed: ${oneLine(error instanceof Error ? error.message : String(error))}`;
5319
4614
  }
5320
4615
  renderFooter();
@@ -5323,7 +4618,6 @@ async function runOperatorBoard(context, options = {}) {
5323
4618
  };
5324
4619
  const answerInput = async (item, text2) => {
5325
4620
  notice = `answering ${item.requestId.slice(0, 12)}\u2026`;
5326
- inboxView.patchItem(item.requestId, `answering\u2026 ${item.summary}`);
5327
4621
  renderFooter();
5328
4622
  tui.requestRender();
5329
4623
  try {
@@ -5336,10 +4630,8 @@ async function runOperatorBoard(context, options = {}) {
5336
4630
  answers: { [item.questionId ?? "response"]: text2 }
5337
4631
  })
5338
4632
  });
5339
- inboxView.removeItem(item.requestId);
5340
4633
  notice = "answer sent \u2014 drone resumes";
5341
4634
  } catch (error) {
5342
- inboxView.patchItem(item.requestId, item.summary);
5343
4635
  notice = `answer failed: ${oneLine(error instanceof Error ? error.message : String(error))}`;
5344
4636
  }
5345
4637
  renderFooter();
@@ -5488,7 +4780,6 @@ async function runOperatorBoard(context, options = {}) {
5488
4780
  const run = list.selectedRun();
5489
4781
  if (run) {
5490
4782
  notice = `stop requested for ${run.runId.slice(0, 8)}\u2026`;
5491
- list.patchRun(run.runId, { status: "stopping" });
5492
4783
  renderFooter();
5493
4784
  tui.requestRender();
5494
4785
  stopRunViaServer(context, run.runId).then(() => refresh()).catch(() => refresh());
@@ -5496,9 +4787,6 @@ async function runOperatorBoard(context, options = {}) {
5496
4787
  return { consume: true };
5497
4788
  }
5498
4789
  if (data === "r") {
5499
- notice = "refreshing fleet\u2026";
5500
- renderFooter();
5501
- tui.requestRender();
5502
4790
  refresh();
5503
4791
  return { consume: true };
5504
4792
  }
@@ -5524,39 +4812,21 @@ async function runOperatorBoard(context, options = {}) {
5524
4812
  tui.requestRender();
5525
4813
  }
5526
4814
  }, BOARD_TICK_MS);
5527
- const live = { subscription: null };
5528
- const refreshActiveView = () => {
5529
- refresh({ quiet: true });
5530
- if (view === "tasks")
5531
- refreshTasks();
5532
- if (view === "inbox")
5533
- refreshInbox();
5534
- };
5535
- connectRigServerEvents(context.projectRoot, {
5536
- onSnapshotInvalidated: () => refreshActiveView()
5537
- }).then((subscription) => {
5538
- live.subscription = subscription;
5539
- }).catch(() => {
5540
- live.subscription = null;
5541
- });
5542
4815
  const refreshTimer = setInterval(() => {
5543
- if (live.subscription?.connected())
5544
- return;
5545
4816
  refresh();
5546
4817
  }, BOARD_REFRESH_MS);
5547
4818
  tui.start();
5548
- refresh({ quiet: true });
5549
- await new Promise((resolve26) => {
4819
+ refresh();
4820
+ await new Promise((resolve25) => {
5550
4821
  const poll = setInterval(() => {
5551
4822
  if (stopped) {
5552
4823
  clearInterval(poll);
5553
- resolve26();
4824
+ resolve25();
5554
4825
  }
5555
4826
  }, 50);
5556
4827
  });
5557
4828
  clearInterval(animation);
5558
4829
  clearInterval(refreshTimer);
5559
- live.subscription?.close();
5560
4830
  return outcome;
5561
4831
  }
5562
4832
  async function runOperatorBoardLoop(context, attach, options = {}) {
@@ -5569,13 +4839,12 @@ async function runOperatorBoardLoop(context, attach, options = {}) {
5569
4839
  await attach(outcome.runId);
5570
4840
  }
5571
4841
  }
5572
- var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS = 16, BOARD_TASK_PAGE = 20;
4842
+ var BOARD_REFRESH_MS = 5000, BOARD_TICK_MS = 250, BOARD_TASK_PAGE = 20;
5573
4843
  var init_board = __esm(() => {
5574
4844
  init_theme();
5575
4845
  init__help_catalog();
5576
4846
  init__server_client();
5577
4847
  init__authority_runs();
5578
- init__server_events();
5579
4848
  init_inbox();
5580
4849
  init_task();
5581
4850
  });
@@ -5586,7 +4855,7 @@ import {
5586
4855
  existsSync as existsSync19,
5587
4856
  readFileSync as readFileSync13
5588
4857
  } from "fs";
5589
- import { resolve as resolve26 } from "path";
4858
+ import { resolve as resolve25 } from "path";
5590
4859
  import { readBuildConfig } from "@rig/runtime/build-time-config";
5591
4860
 
5592
4861
  // packages/cli/src/commands/browser.ts
@@ -8093,7 +7362,7 @@ import {
8093
7362
  chmodSync,
8094
7363
  copyFileSync as copyFileSync2,
8095
7364
  existsSync as existsSync9,
8096
- mkdirSync as mkdirSync8,
7365
+ mkdirSync as mkdirSync7,
8097
7366
  readdirSync,
8098
7367
  readlinkSync,
8099
7368
  rmSync as rmSync3,
@@ -8210,7 +7479,7 @@ async function executeDist(context, args) {
8210
7479
  requireNoExtraArgs(pending, "rig dist install [--scope user|system] [--path <dir>]");
8211
7480
  const scope = parseInstallScope(scopeResult.value);
8212
7481
  const installDir = resolveInstallDir(scope, pathResult.value);
8213
- mkdirSync8(installDir, { recursive: true });
7482
+ mkdirSync7(installDir, { recursive: true });
8214
7483
  let source = await findLatestDistBinary(context.projectRoot);
8215
7484
  let buildDir = null;
8216
7485
  if (!source) {
@@ -8265,7 +7534,7 @@ async function executeDist(context, args) {
8265
7534
  const fp = await computeRuntimeImageFingerprint(context.projectRoot);
8266
7535
  const currentId = computeRuntimeImageId(fp);
8267
7536
  const imagesDir = resolve14(resolveControlPlaneMonorepoRuntimeDir(context.projectRoot), "images");
8268
- mkdirSync8(imagesDir, { recursive: true });
7537
+ mkdirSync7(imagesDir, { recursive: true });
8269
7538
  let pruned = 0;
8270
7539
  for (const entry of readdirSync(imagesDir, { withFileTypes: true })) {
8271
7540
  if (entry.isDirectory() && entry.name !== currentId) {
@@ -8277,9 +7546,9 @@ async function executeDist(context, args) {
8277
7546
  console.log(`Pruned ${pruned} stale image(s).`);
8278
7547
  }
8279
7548
  const imageDir = resolve14(imagesDir, currentId);
8280
- mkdirSync8(resolve14(imageDir, "bin/hooks"), { recursive: true });
8281
- mkdirSync8(resolve14(imageDir, "bin/plugins"), { recursive: true });
8282
- mkdirSync8(resolve14(imageDir, "bin/validators"), { recursive: true });
7549
+ mkdirSync7(resolve14(imageDir, "bin/hooks"), { recursive: true });
7550
+ mkdirSync7(resolve14(imageDir, "bin/plugins"), { recursive: true });
7551
+ mkdirSync7(resolve14(imageDir, "bin/validators"), { recursive: true });
8283
7552
  const hookNames = [
8284
7553
  "scope-guard",
8285
7554
  "import-guard",
@@ -8304,8 +7573,8 @@ async function executeDist(context, args) {
8304
7573
  const binPluginsDir = resolve14(resolveControlPlaneHostBinDir(context.projectRoot), "plugins");
8305
7574
  const validatorsRoot = resolve14(hostProjectRoot, "packages/runtime/src/control-plane/validators");
8306
7575
  const binValidatorsDir = resolve14(resolveControlPlaneHostBinDir(context.projectRoot), "validators");
8307
- mkdirSync8(binPluginsDir, { recursive: true });
8308
- mkdirSync8(binValidatorsDir, { recursive: true });
7576
+ mkdirSync7(binPluginsDir, { recursive: true });
7577
+ mkdirSync7(binValidatorsDir, { recursive: true });
8309
7578
  if (existsSync9(pluginsDir)) {
8310
7579
  for (const entry of readdirSync(pluginsDir, { withFileTypes: true })) {
8311
7580
  const m = entry.name.match(/^(.+)\.plugin\.(ts|js|mjs|cjs)$/);
@@ -8412,7 +7681,7 @@ init_inbox();
8412
7681
  init_runner();
8413
7682
  init__connection_state();
8414
7683
  init__server_client();
8415
- import { appendFileSync as appendFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync9, readFileSync as readFileSync7, writeFileSync as writeFileSync6 } from "fs";
7684
+ import { appendFileSync as appendFileSync2, existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync7, writeFileSync as writeFileSync5 } from "fs";
8416
7685
  import { spawnSync } from "child_process";
8417
7686
  import { basename as basename2, resolve as resolve18 } from "path";
8418
7687
  import { buildRigInitConfigSource } from "@rig/core";
@@ -8598,7 +7867,7 @@ async function buildPiSetupChecks(input = {}) {
8598
7867
  // packages/cli/src/commands/_snapshot-upload.ts
8599
7868
  init__server_client();
8600
7869
  import { mkdir, readdir, readFile, writeFile } from "fs/promises";
8601
- import { dirname as dirname4, resolve as resolve16, relative, sep } from "path";
7870
+ import { dirname as dirname3, resolve as resolve16, relative, sep } from "path";
8602
7871
  var SNAPSHOT_ARCHIVE_VERSION = 1;
8603
7872
  var SNAPSHOT_ARCHIVE_CONTENT_TYPE = "application/vnd.rig.snapshot+json";
8604
7873
  var DEFAULT_EXCLUDED_DIRECTORIES = new Set([
@@ -8947,14 +8216,14 @@ function parseRepoSlug(value) {
8947
8216
  }
8948
8217
  function ensureRigPrivateDirs(projectRoot) {
8949
8218
  const rigDir = resolve18(projectRoot, ".rig");
8950
- mkdirSync9(resolve18(rigDir, "state"), { recursive: true });
8951
- mkdirSync9(resolve18(rigDir, "logs"), { recursive: true });
8952
- mkdirSync9(resolve18(rigDir, "runs"), { recursive: true });
8953
- mkdirSync9(resolve18(rigDir, "tmp"), { recursive: true });
8954
- mkdirSync9(resolve18(projectRoot, "artifacts"), { recursive: true });
8219
+ mkdirSync8(resolve18(rigDir, "state"), { recursive: true });
8220
+ mkdirSync8(resolve18(rigDir, "logs"), { recursive: true });
8221
+ mkdirSync8(resolve18(rigDir, "runs"), { recursive: true });
8222
+ mkdirSync8(resolve18(rigDir, "tmp"), { recursive: true });
8223
+ mkdirSync8(resolve18(projectRoot, "artifacts"), { recursive: true });
8955
8224
  const taskConfigPath = resolve18(rigDir, "task-config.json");
8956
8225
  if (!existsSync12(taskConfigPath))
8957
- writeFileSync6(taskConfigPath, `{}
8226
+ writeFileSync5(taskConfigPath, `{}
8958
8227
  `, "utf-8");
8959
8228
  }
8960
8229
  function ensureGitignoreEntries(projectRoot) {
@@ -8982,7 +8251,7 @@ function ensureRigConfigPackageDependencies(projectRoot) {
8982
8251
  ...existsSync12(path) ? existing : { name: "rig-project", private: true },
8983
8252
  devDependencies
8984
8253
  };
8985
- writeFileSync6(path, `${JSON.stringify(next, null, 2)}
8254
+ writeFileSync5(path, `${JSON.stringify(next, null, 2)}
8986
8255
  `, "utf8");
8987
8256
  }
8988
8257
  function applyGitHubProjectConfig(source, options) {
@@ -9008,9 +8277,9 @@ function checkoutForInit(projectRoot, serverKind, strategy) {
9008
8277
  const selected = strategy ?? { kind: "managed-clone" };
9009
8278
  switch (selected.kind) {
9010
8279
  case "managed-clone":
9011
- return { kind: "managed-clone" };
8280
+ return { kind: "managed-clone", path: projectRoot };
9012
8281
  case "current-ref":
9013
- return { kind: "current-ref", ...selected.ref ? { ref: selected.ref } : {} };
8282
+ return { kind: "current-ref", path: projectRoot, ...selected.ref ? { ref: selected.ref } : {} };
9014
8283
  case "uploaded-snapshot":
9015
8284
  return { kind: "uploaded-snapshot", path: projectRoot, source: "local-working-tree" };
9016
8285
  case "existing-path":
@@ -9280,7 +8549,7 @@ function remoteGitHubAuthMetadata(payload) {
9280
8549
  };
9281
8550
  }
9282
8551
  function writeRemoteGitHubAuthState(projectRoot, input) {
9283
- writeFileSync6(resolve18(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
8552
+ writeFileSync5(resolve18(projectRoot, ".rig", "state", "github-auth.json"), `${JSON.stringify({
9284
8553
  authenticated: true,
9285
8554
  source: input.source,
9286
8555
  storedOnServer: true,
@@ -9328,7 +8597,7 @@ function runLocalFilesInit(context, options) {
9328
8597
  console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it.");
9329
8598
  } else {
9330
8599
  const projectName = basename2(projectRoot) || "rig-project";
9331
- writeFileSync6(configTsPath, buildRigInitConfigSource({
8600
+ writeFileSync5(configTsPath, buildRigInitConfigSource({
9332
8601
  projectName,
9333
8602
  taskSource: { kind: "files", path: "tasks" },
9334
8603
  useStandardPlugin: true
@@ -9337,8 +8606,8 @@ function runLocalFilesInit(context, options) {
9337
8606
  ensureRigConfigPackageDependencies(projectRoot);
9338
8607
  const tasksDir = resolve18(projectRoot, "tasks");
9339
8608
  if (!existsSync12(tasksDir)) {
9340
- mkdirSync9(tasksDir, { recursive: true });
9341
- writeFileSync6(resolve18(tasksDir, "T-1.json"), `${JSON.stringify({ id: "T-1", title: "My first Rig task", body: "Describe the change you want an agent to make." }, null, 2)}
8609
+ mkdirSync8(tasksDir, { recursive: true });
8610
+ writeFileSync5(resolve18(tasksDir, "T-1.json"), `${JSON.stringify({ id: "T-1", title: "My first Rig task", body: "Describe the change you want an agent to make." }, null, 2)}
9342
8611
  `, "utf-8");
9343
8612
  }
9344
8613
  if (context.outputMode !== "json") {
@@ -9401,7 +8670,7 @@ function runDemoInit(context, options) {
9401
8670
  console.log("rig.config already exists; leaving it unchanged. Pass --repair to rewrite it for the demo.");
9402
8671
  }
9403
8672
  } else {
9404
- writeFileSync6(configTsPath, buildRigInitConfigSource({
8673
+ writeFileSync5(configTsPath, buildRigInitConfigSource({
9405
8674
  projectName: basename2(projectRoot) || "rig-demo",
9406
8675
  taskSource: { kind: "files", path: DEMO_TASKS_RELATIVE_DIR },
9407
8676
  useStandardPlugin: true
@@ -9410,14 +8679,14 @@ function runDemoInit(context, options) {
9410
8679
  }
9411
8680
  ensureRigConfigPackageDependencies(projectRoot);
9412
8681
  const demoTasksDir = resolve18(projectRoot, DEMO_TASKS_RELATIVE_DIR);
9413
- mkdirSync9(demoTasksDir, { recursive: true });
8682
+ mkdirSync8(demoTasksDir, { recursive: true });
9414
8683
  const taskIds = [];
9415
8684
  for (const task of DEMO_TASKS) {
9416
8685
  const id = String(task.id);
9417
8686
  taskIds.push(id);
9418
8687
  const taskPath = resolve18(demoTasksDir, `${id}.json`);
9419
8688
  if (!existsSync12(taskPath)) {
9420
- writeFileSync6(taskPath, `${JSON.stringify(task, null, 2)}
8689
+ writeFileSync5(taskPath, `${JSON.stringify(task, null, 2)}
9421
8690
  `, "utf-8");
9422
8691
  }
9423
8692
  }
@@ -9445,32 +8714,21 @@ function runDemoInit(context, options) {
9445
8714
  }
9446
8715
  async function runControlPlaneInit(context, options) {
9447
8716
  const projectRoot = context.projectRoot;
9448
- const existingRepoConnection = readRepoConnection(projectRoot);
9449
- const selectedConnection = (() => {
9450
- try {
9451
- return resolveSelectedConnection(projectRoot);
9452
- } catch {
9453
- return null;
9454
- }
9455
- })();
9456
- const selectedRemote = selectedConnection?.connection.kind === "remote" ? { alias: selectedConnection.alias, connection: selectedConnection.connection } : null;
9457
- const detectedSlug = options.repoSlug ?? existingRepoConnection?.project ?? detectOriginRepoSlug(projectRoot);
9458
- const serverKind = options.server ?? (selectedRemote ? "remote" : "local");
8717
+ const detectedSlug = options.repoSlug ?? detectOriginRepoSlug(projectRoot);
9459
8718
  if (!detectedSlug) {
9460
8719
  const authMethod2 = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
9461
- if (serverKind === "local" && authMethod2 === "skip") {
8720
+ if ((options.server ?? "local") === "local" && authMethod2 === "skip") {
9462
8721
  return runLocalFilesInit(context, options);
9463
8722
  }
9464
8723
  throw new CliError("Could not detect GitHub repo slug from origin. Pass --repo owner/repo \u2014 or run `rig init --yes --server local --github-auth skip` for a local files-source project without GitHub.", 1);
9465
8724
  }
9466
8725
  const repo = parseRepoSlug(detectedSlug);
9467
- const connectionAlias = options.connectionAlias ?? (serverKind === "local" ? "local" : selectedRemote?.alias ?? "remote");
9468
- const selectedRemoteUrl = selectedRemote && (!options.connectionAlias || options.connectionAlias === selectedRemote.alias) ? selectedRemote.connection.baseUrl : undefined;
9469
- const remoteUrl = serverKind === "remote" ? (options.remoteUrl ?? selectedRemoteUrl)?.replace(/\/+$/, "") : undefined;
8726
+ const serverKind = options.server ?? "local";
8727
+ const connectionAlias = options.connectionAlias ?? (serverKind === "local" ? "local" : "remote");
9470
8728
  if (serverKind === "remote") {
9471
- if (!remoteUrl)
9472
- throw new CliError("Missing --remote-url for --server remote.", 1, { hint: "Re-run as `rig init --server remote --remote-url https://your-rig-server`, or first select a saved remote with `rig server use <alias>`." });
9473
- upsertGlobalConnection(connectionAlias, { kind: "remote", baseUrl: remoteUrl });
8729
+ if (!options.remoteUrl)
8730
+ throw new CliError("Missing --remote-url for --server remote.", 1, { hint: "Re-run as `rig init --server remote --remote-url https://your-rig-server`." });
8731
+ upsertGlobalConnection(connectionAlias, { kind: "remote", baseUrl: options.remoteUrl });
9474
8732
  }
9475
8733
  writeRepoConnection(projectRoot, {
9476
8734
  selected: connectionAlias,
@@ -9493,11 +8751,11 @@ async function runControlPlaneInit(context, options) {
9493
8751
  taskSource: { kind: "github-issues", owner: repo.owner, repo: repo.repo },
9494
8752
  useStandardPlugin: true
9495
8753
  }), options);
9496
- writeFileSync6(configTsPath, source, "utf-8");
8754
+ writeFileSync5(configTsPath, source, "utf-8");
9497
8755
  }
9498
8756
  ensureRigConfigPackageDependencies(projectRoot);
9499
8757
  }
9500
- writeFileSync6(resolve18(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
8758
+ writeFileSync5(resolve18(projectRoot, ".rig", "state", "project-link.json"), `${JSON.stringify({ repoSlug: repo.slug, connection: connectionAlias, linkedAt: new Date().toISOString() }, null, 2)}
9501
8759
  `, "utf8");
9502
8760
  const checkout = checkoutForInit(projectRoot, serverKind, options.remoteCheckout);
9503
8761
  let uploadedSnapshot = null;
@@ -9512,7 +8770,7 @@ async function runControlPlaneInit(context, options) {
9512
8770
  let githubAuth = null;
9513
8771
  let deviceAuth = null;
9514
8772
  const authMethod = options.githubAuthMethod ?? (options.githubToken ? "token" : "skip");
9515
- const remoteGhTokenWarning = serverKind === "remote" && authMethod === "gh" ? `This sends a GitHub token from this machine to ${remoteUrl ?? "the remote Rig server"}.` : null;
8773
+ const remoteGhTokenWarning = serverKind === "remote" && authMethod === "gh" ? `This sends a GitHub token from this machine to ${options.remoteUrl ?? "the remote Rig server"}.` : null;
9516
8774
  if (remoteGhTokenWarning && !options.yes) {
9517
8775
  throw new CliError(`${remoteGhTokenWarning} Re-run with --yes to confirm this explicit token transfer.`, 1);
9518
8776
  }
@@ -9825,64 +9083,14 @@ Usage: rig init`, 1);
9825
9083
  // packages/cli/src/commands/github.ts
9826
9084
  init_runner();
9827
9085
  init__server_client();
9828
- init__connection_state();
9829
9086
  init__async_ui();
9830
9087
  import { spawnSync as spawnSync2 } from "child_process";
9831
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync7 } from "fs";
9832
- import { dirname as dirname5, resolve as resolve19 } from "path";
9833
9088
  function printPayload(context, payload, fallback) {
9834
9089
  if (context.outputMode === "json")
9835
9090
  console.log(JSON.stringify(payload, null, 2));
9836
9091
  else
9837
9092
  console.log(fallback);
9838
9093
  }
9839
- function apiSessionTokenFrom2(payload) {
9840
- if (!payload || typeof payload !== "object" || Array.isArray(payload))
9841
- return null;
9842
- const token = payload.apiSessionToken;
9843
- return typeof token === "string" && token.trim() ? token.trim() : null;
9844
- }
9845
- function payloadString(payload, key) {
9846
- const value = payload[key];
9847
- return typeof value === "string" && value.trim() ? value.trim() : null;
9848
- }
9849
- function payloadRecord(payload, key) {
9850
- const value = payload[key];
9851
- return value && typeof value === "object" && !Array.isArray(value) ? value : null;
9852
- }
9853
- function remoteNamespaceMetadata(result) {
9854
- const namespace = payloadRecord(result, "userNamespace");
9855
- return {
9856
- ...payloadString(result, "login") ? { login: payloadString(result, "login") } : {},
9857
- ...payloadString(result, "userId") ? { userId: payloadString(result, "userId") } : {},
9858
- ...namespace && payloadString(namespace, "key") ? { userNamespaceKey: payloadString(namespace, "key") } : {},
9859
- ...namespace && payloadString(namespace, "root") ? { userNamespaceRoot: payloadString(namespace, "root") } : {},
9860
- ...namespace && payloadString(namespace, "checkoutBaseDir") ? { checkoutBaseDir: payloadString(namespace, "checkoutBaseDir") } : {},
9861
- ...namespace && payloadString(namespace, "snapshotBaseDir") ? { snapshotBaseDir: payloadString(namespace, "snapshotBaseDir") } : {}
9862
- };
9863
- }
9864
- function persistRemoteAuthSession(context, source, result, fallbackToken) {
9865
- const apiSessionToken = apiSessionTokenFrom2(result);
9866
- setGitHubBearerTokenForCurrentProcess(apiSessionToken ?? fallbackToken, context.projectRoot);
9867
- if (!apiSessionToken)
9868
- return;
9869
- const repo = readRepoConnection(context.projectRoot);
9870
- const path = resolve19(context.projectRoot, ".rig", "state", "github-auth.json");
9871
- mkdirSync10(dirname5(path), { recursive: true });
9872
- writeFileSync7(path, `${JSON.stringify({
9873
- authenticated: true,
9874
- source,
9875
- storedOnServer: true,
9876
- ...repo?.project ? { selectedRepo: repo.project } : {},
9877
- ...remoteNamespaceMetadata(result),
9878
- apiSessionToken,
9879
- updatedAt: new Date().toISOString()
9880
- }, null, 2)}
9881
- `, "utf8");
9882
- }
9883
- function isSignedIn(status) {
9884
- return status.signedIn === true || status.authenticated === true;
9885
- }
9886
9094
  function readGhToken() {
9887
9095
  const result = spawnSync2("gh", ["auth", "token"], { encoding: "utf8" });
9888
9096
  if (result.status !== 0) {
@@ -9904,7 +9112,7 @@ async function executeGithub(context, args) {
9904
9112
  if (rest.length > 0)
9905
9113
  throw new CliError("Usage: rig github auth status", 1);
9906
9114
  const status = await withSpinner("Checking GitHub auth on the server\u2026", () => getGitHubAuthStatusViaServer(context), { outputMode: context.outputMode });
9907
- printPayload(context, status, `GitHub auth: ${isSignedIn(status) ? "authenticated" : "unauthenticated"}`);
9115
+ printPayload(context, status, `GitHub auth: ${status.authenticated ? "authenticated" : "unauthenticated"}`);
9908
9116
  return { ok: true, group: "github", command: "auth status", details: status };
9909
9117
  }
9910
9118
  case "token": {
@@ -9914,20 +9122,16 @@ async function executeGithub(context, args) {
9914
9122
  const token = parsed.value?.trim();
9915
9123
  if (!token)
9916
9124
  throw new CliError("Missing --token value.", 1, { hint: "Re-run as `rig github auth token --token <token>`." });
9917
- const repo = readRepoConnection(context.projectRoot);
9918
- const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token, repo?.project ? { selectedRepo: repo.project } : {}), { outputMode: context.outputMode });
9919
- persistRemoteAuthSession(context, "token", result, token);
9920
- printPayload(context, result, "GitHub token stored on the selected server.");
9125
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, token), { outputMode: context.outputMode });
9126
+ printPayload(context, result, "GitHub token stored on the selected Rig server.");
9921
9127
  return { ok: true, group: "github", command: "auth token", details: result };
9922
9128
  }
9923
9129
  case "import-gh": {
9924
9130
  if (rest.length > 0)
9925
9131
  throw new CliError("Usage: rig github auth import-gh", 1);
9926
9132
  const importedToken = readGhToken();
9927
- const repo = readRepoConnection(context.projectRoot);
9928
- const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken, repo?.project ? { selectedRepo: repo.project } : {}), { outputMode: context.outputMode });
9929
- persistRemoteAuthSession(context, "gh", result, importedToken);
9930
- printPayload(context, result, "GitHub token imported from gh and stored on the selected server.");
9133
+ const result = await withSpinner("Storing GitHub token on the server\u2026", () => postGitHubTokenViaServer(context, importedToken), { outputMode: context.outputMode });
9134
+ printPayload(context, result, "GitHub token imported from gh and stored on the selected Rig server.");
9931
9135
  return { ok: true, group: "github", command: "auth import-gh", details: result };
9932
9136
  }
9933
9137
  default:
@@ -9957,7 +9161,7 @@ init_runner();
9957
9161
  init__authority_runs();
9958
9162
  init__paths();
9959
9163
  import { readFileSync as readFileSync8 } from "fs";
9960
- import { resolve as resolve20 } from "path";
9164
+ import { resolve as resolve19 } from "path";
9961
9165
  import {
9962
9166
  appendRunJournalEvent,
9963
9167
  appendRunLogEntry,
@@ -9994,7 +9198,7 @@ function touchAuthorityRun(projectRoot, runId) {
9994
9198
  if (!current) {
9995
9199
  return;
9996
9200
  }
9997
- writeJsonFile3(resolve20(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
9201
+ writeJsonFile3(resolve19(resolveAuthorityRunDir(projectRoot, runId), "run.json"), {
9998
9202
  ...current,
9999
9203
  updatedAt: new Date().toISOString()
10000
9204
  });
@@ -10232,7 +9436,7 @@ init_runner();
10232
9436
  init__server_client();
10233
9437
  init__async_ui();
10234
9438
  import { existsSync as existsSync13, readFileSync as readFileSync9 } from "fs";
10235
- import { resolve as resolve21 } from "path";
9439
+ import { resolve as resolve20 } from "path";
10236
9440
  import {
10237
9441
  listAuthorityRuns,
10238
9442
  readAuthorityRun as readAuthorityRun3,
@@ -10276,7 +9480,7 @@ async function executeInspect(context, args) {
10276
9480
  }
10277
9481
  return { ok: true, group: "inspect", command, details: { task: requiredTask, runId: fallback.runId, source: "server", entries } };
10278
9482
  }
10279
- const logsPath = resolve21(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
9483
+ const logsPath = resolve20(resolveAuthorityRunDir2(context.projectRoot, latestRun.runId), "logs.jsonl");
10280
9484
  if (!existsSync13(logsPath)) {
10281
9485
  throw new CliError(`No logs found for run ${latestRun.runId}.`, 1, { hint: `Try \`rig run show ${latestRun.runId}\` or \`rig run replay ${latestRun.runId}\`.` });
10282
9486
  }
@@ -10364,7 +9568,7 @@ async function executeInspect(context, args) {
10364
9568
  return { ok: true, group: "inspect", command };
10365
9569
  case "audit": {
10366
9570
  requireNoExtraArgs(rest, "rig inspect audit");
10367
- const auditPath = resolve21(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
9571
+ const auditPath = resolve20(resolveHarnessPaths2(context.projectRoot).logsDir, "audit.jsonl");
10368
9572
  if (!existsSync13(auditPath)) {
10369
9573
  console.log("No audit log found.");
10370
9574
  } else {
@@ -11023,7 +10227,7 @@ import { loadRuntimeContextFromEnv } from "@rig/runtime/control-plane/runtime/co
11023
10227
 
11024
10228
  // packages/cli/src/commands/_run-replay.ts
11025
10229
  import { existsSync as existsSync14, readdirSync as readdirSync2 } from "fs";
11026
- import { join as join2, resolve as resolve22 } from "path";
10230
+ import { join as join2, resolve as resolve21 } from "path";
11027
10231
  import {
11028
10232
  readAuthorityRun as readAuthorityRun4,
11029
10233
  readJsonlFile as readJsonlFile3,
@@ -11116,7 +10320,7 @@ function resolveRunSessionFile(record) {
11116
10320
  const sessionId = text(piSession.sessionId);
11117
10321
  if (!cwd || !sessionId)
11118
10322
  return null;
11119
- const sessionDir = resolve22(cwd, ".rig", "session");
10323
+ const sessionDir = resolve21(cwd, ".rig", "session");
11120
10324
  try {
11121
10325
  const match = readdirSync2(sessionDir).find((name) => name.endsWith(`_${sessionId}.jsonl`));
11122
10326
  return match ? join2(sessionDir, match) : null;
@@ -11614,9 +10818,6 @@ async function executeRun(context, args) {
11614
10818
  console.log(`Stop requested: ${runId}`);
11615
10819
  return { ok: true, group: "run", command, details: stopped };
11616
10820
  }
11617
- if (isRemoteConnectionSelected(context.projectRoot)) {
11618
- throw new CliError("Remote run stop requires an explicit run id.", 2, { hint: "Run `rig run list`, then `rig run stop <run-id>`." });
11619
- }
11620
10821
  const result = await runStop(context.projectRoot);
11621
10822
  if (result.remaining.length > 0) {
11622
10823
  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." });
@@ -11649,7 +10850,6 @@ init_drone_ui();
11649
10850
  init_runner();
11650
10851
  init__connection_state();
11651
10852
  init__cli_format();
11652
- init__server_client();
11653
10853
  function usageName(options) {
11654
10854
  return `rig ${options.group}`;
11655
10855
  }
@@ -11669,46 +10869,13 @@ function parseConnection(alias, value, options) {
11669
10869
  }
11670
10870
  return { kind: "remote", baseUrl: parsed.toString().replace(/\/+$/, "") };
11671
10871
  }
11672
- function printJsonOrText(context, _payload, text2) {
11673
- if (context.outputMode !== "json") {
10872
+ function printJsonOrText(context, payload, text2) {
10873
+ if (context.outputMode === "json") {
10874
+ console.log(JSON.stringify(payload, null, 2));
10875
+ } else {
11674
10876
  console.log(text2);
11675
10877
  }
11676
10878
  }
11677
- function formatRemoteProjectLinkText(result) {
11678
- return formatSuccessCard(result.ok ? "Remote project link ready" : "Remote project link needs repair", [
11679
- ["selected", result.alias ?? "remote"],
11680
- ["target", result.baseUrl ?? "unknown"],
11681
- ["repo", result.repoSlug ?? "owner/repo"],
11682
- ["status", result.status],
11683
- ...result.serverProjectRoot ? [["server root", result.serverProjectRoot]] : [],
11684
- ["next", result.ok ? result.next ?? "rig task list" : result.hint]
11685
- ]);
11686
- }
11687
- function parseRepairLinkArgs(rest, usage) {
11688
- let repoSlug;
11689
- let mode = "prepare-if-missing";
11690
- const pending = [...rest];
11691
- while (pending.length > 0) {
11692
- const token = pending.shift();
11693
- if (token === "--repo") {
11694
- const value = pending.shift()?.trim();
11695
- if (!value)
11696
- throw new CliError(`Missing --repo value. Usage: ${usage}`, 1);
11697
- const normalized = normalizeRepoSlug(value);
11698
- if (!normalized)
11699
- throw new CliError(`Invalid --repo value: ${value}`, 1, { hint: "Use the canonical owner/repo slug, e.g. `--repo humanity-org/humanwork`." });
11700
- repoSlug = normalized;
11701
- } else if (token === "--backfill-only") {
11702
- mode = "backfill-only";
11703
- } else if (token === "--prepare") {
11704
- mode = "prepare-if-missing";
11705
- } else {
11706
- throw new CliError(`Unexpected argument: ${String(token)}
11707
- Usage: ${usage}`, 1);
11708
- }
11709
- }
11710
- return { repoSlug, mode };
11711
- }
11712
10879
  async function promptForConnectionAlias(context) {
11713
10880
  const state = readGlobalConnections();
11714
10881
  const repo = readRepoConnection(context.projectRoot);
@@ -11762,67 +10929,31 @@ async function executeConnectionCommand(context, args, options) {
11762
10929
  }
11763
10930
  if (!alias)
11764
10931
  throw new CliError(`Missing alias. Usage: ${usageName(options)} use <alias|local>`, 1);
11765
- let selectedConnection = { kind: "local", mode: "auto" };
11766
10932
  if (alias !== "local") {
11767
10933
  const state = readGlobalConnections();
11768
- const connection = state.connections[alias];
11769
- if (!connection)
10934
+ if (!state.connections[alias])
11770
10935
  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>`." });
11771
- selectedConnection = connection;
11772
- }
11773
- const previousRepo = readRepoConnection(context.projectRoot);
11774
- const preserveRemoteRoot = Boolean(previousRepo?.serverProjectRoot && previousRepo.selected === alias && selectedConnection.kind === "remote" && previousRepo.serverProjectRootAlias === alias && previousRepo.serverProjectRootBaseUrl === selectedConnection.baseUrl);
11775
- const repoState = {
11776
- selected: alias,
11777
- ...previousRepo?.project ? { project: previousRepo.project } : {},
11778
- linkedAt: new Date().toISOString(),
11779
- ...preserveRemoteRoot ? {
11780
- serverProjectRoot: previousRepo.serverProjectRoot,
11781
- serverProjectRootAlias: previousRepo.serverProjectRootAlias,
11782
- serverProjectRootBaseUrl: previousRepo.serverProjectRootBaseUrl
11783
- } : {}
11784
- };
10936
+ }
10937
+ const repoState = { selected: alias, linkedAt: new Date().toISOString() };
11785
10938
  writeRepoConnection(context.projectRoot, repoState);
11786
- const remoteProjectLink = alias !== "local" ? await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only" }).catch((error) => ({
11787
- ok: false,
11788
- status: "error",
11789
- message: error instanceof Error ? error.message : String(error),
11790
- hint: "Run `rig server repair-link` after authenticating the selected remote."
11791
- })) : null;
11792
- const latestRepo = readRepoConnection(context.projectRoot);
11793
- const details = { selected: latestRepo?.selected ?? alias, repo: latestRepo, remoteProjectLink };
11794
- printJsonOrText(context, details, formatSuccessCard("Rig server selected", [
10939
+ printJsonOrText(context, repoState, formatSuccessCard("Rig server selected", [
11795
10940
  ["selected", alias],
11796
10941
  ["scope", "this repo"],
11797
- ...remoteProjectLink ? [["remote link", remoteProjectLink.ok ? `ready (${remoteProjectLink.serverProjectRoot ?? "linked"})` : `${remoteProjectLink.status}: ${remoteProjectLink.hint}`]] : [],
11798
- ["next", remoteProjectLink && !remoteProjectLink.ok ? "rig server repair-link" : "rig task list"]
10942
+ ["next", "rig task list"]
11799
10943
  ]));
11800
- return { ok: true, group: options.group, command: "use", details };
11801
- }
11802
- case "repair-link": {
11803
- const parsed = parseRepairLinkArgs(rest, `${usageName(options)} repair-link [--prepare|--backfill-only] [--repo owner/repo]`);
11804
- const result = await repairRemoteProjectRootLink(context, parsed);
11805
- printJsonOrText(context, result, formatRemoteProjectLinkText(result));
11806
- return { ok: true, group: options.group, command: "repair-link", details: result };
10944
+ return { ok: true, group: options.group, command: "use", details: repoState };
11807
10945
  }
11808
10946
  case "status": {
11809
10947
  requireNoExtraArgs(rest, `${usageName(options)} status`);
11810
10948
  const repo = readRepoConnection(context.projectRoot);
11811
10949
  const global = readGlobalConnections();
11812
- const remoteProjectLink = repo?.selected && repo.selected !== "local" ? await ensureRemoteProjectRootLink(context.projectRoot, { mode: "backfill-only" }).catch((error) => ({
11813
- ok: false,
11814
- status: "error",
11815
- message: error instanceof Error ? error.message : String(error),
11816
- hint: "Run `rig server repair-link` after authenticating the selected remote."
11817
- })) : null;
11818
- const latestRepo = readRepoConnection(context.projectRoot) ?? repo;
11819
- const details = { selected: latestRepo?.selected ?? "local", repo: latestRepo, connections: global.connections, remoteProjectLink };
11820
- printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections, latestRepo ?? null, remoteProjectLink));
10950
+ const details = { selected: repo?.selected ?? "local", repo, connections: global.connections };
10951
+ printJsonOrText(context, details, formatConnectionStatus(details.selected, global.connections));
11821
10952
  return { ok: true, group: options.group, command: "status", details };
11822
10953
  }
11823
10954
  default:
11824
10955
  throw new CliError(`Unknown ${options.group} command: ${String(command)}
11825
- Usage: ${usageName(options)} <list|add|use|status|repair-link>`, 1);
10956
+ Usage: ${usageName(options)} <list|add|use|status>`, 1);
11826
10957
  }
11827
10958
  }
11828
10959
 
@@ -11830,7 +10961,7 @@ Usage: ${usageName(options)} <list|add|use|status|repair-link>`, 1);
11830
10961
  init__server_client();
11831
10962
  async function executeServer(context, args, options) {
11832
10963
  const [command = "status", ...rest] = args;
11833
- if (["status", "list", "add", "use", "repair-link"].includes(command)) {
10964
+ if (["status", "list", "add", "use"].includes(command)) {
11834
10965
  return executeConnectionCommand(context, [command, ...rest], { group: "server", interactiveUse: true });
11835
10966
  }
11836
10967
  switch (command) {
@@ -12038,8 +11169,8 @@ init_task();
12038
11169
 
12039
11170
  // packages/cli/src/commands/task-run-driver.ts
12040
11171
  init_runner();
12041
- import { copyFileSync as copyFileSync3, existsSync as existsSync16, mkdirSync as mkdirSync12, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync9 } from "fs";
12042
- import { resolve as resolve24 } from "path";
11172
+ import { copyFileSync as copyFileSync3, existsSync as existsSync16, mkdirSync as mkdirSync10, readFileSync as readFileSync12, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
11173
+ import { resolve as resolve23 } from "path";
12043
11174
  import { spawn as spawn2, spawnSync as spawnSync4 } from "child_process";
12044
11175
  import { createInterface as createLineInterface } from "readline";
12045
11176
  import { loadConfig as loadConfig2 } from "@rig/core/load-config";
@@ -12138,12 +11269,12 @@ function copyUntrackedDirtyFiles(sourceRoot, targetRoot) {
12138
11269
  return 0;
12139
11270
  let copied = 0;
12140
11271
  for (const relativePath of listed.stdout.split("\x00").filter(Boolean)) {
12141
- const sourcePath = resolve24(sourceRoot, relativePath);
12142
- const targetPath = resolve24(targetRoot, relativePath);
11272
+ const sourcePath = resolve23(sourceRoot, relativePath);
11273
+ const targetPath = resolve23(targetRoot, relativePath);
12143
11274
  try {
12144
11275
  if (!statSync2(sourcePath).isFile())
12145
11276
  continue;
12146
- mkdirSync12(resolve24(targetPath, ".."), { recursive: true });
11277
+ mkdirSync10(resolve23(targetPath, ".."), { recursive: true });
12147
11278
  copyFileSync3(sourcePath, targetPath);
12148
11279
  copied += 1;
12149
11280
  } catch {}
@@ -12182,7 +11313,7 @@ function buildDirtyBaselineHandshakeEnv(input) {
12182
11313
  return { RIG_BASELINE_MODE: input.baselineMode ?? "head" };
12183
11314
  return {
12184
11315
  RIG_BASELINE_MODE: "dirty-snapshot",
12185
- RIG_DIRTY_BASELINE_READY_FILE: resolve24(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
11316
+ RIG_DIRTY_BASELINE_READY_FILE: resolve23(input.projectRoot, ".rig", "runs", input.runId, "dirty-baseline.ready.json")
12186
11317
  };
12187
11318
  }
12188
11319
  function positiveInt(value, fallback) {
@@ -12287,9 +11418,9 @@ function createCommandRunner(binary) {
12287
11418
  const stderrChunks = [];
12288
11419
  child.stdout.on("data", (chunk) => stdoutChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
12289
11420
  child.stderr.on("data", (chunk) => stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk))));
12290
- return await new Promise((resolve25) => {
12291
- child.once("error", (error) => resolve25({ exitCode: 1, stderr: error.message }));
12292
- child.once("close", (code) => resolve25({
11421
+ return await new Promise((resolve24) => {
11422
+ child.once("error", (error) => resolve24({ exitCode: 1, stderr: error.message }));
11423
+ child.once("close", (code) => resolve24({
12293
11424
  exitCode: code ?? 1,
12294
11425
  stdout: Buffer.concat(stdoutChunks).toString("utf8"),
12295
11426
  stderr: Buffer.concat(stderrChunks).toString("utf8")
@@ -12363,7 +11494,7 @@ async function runTaskRunPostValidationLifecycle(input) {
12363
11494
  config,
12364
11495
  sourceTask: input.sourceTask,
12365
11496
  uploadedSnapshot: input.uploadedSnapshot,
12366
- artifactRoot: resolve24(input.projectRoot, "artifacts", taskId3),
11497
+ artifactRoot: resolve23(input.projectRoot, "artifacts", taskId3),
12367
11498
  command: ghCommand,
12368
11499
  gitCommand,
12369
11500
  steerPi,
@@ -12493,7 +11624,7 @@ function summarizeValidationFailure(projectRoot, taskId3) {
12493
11624
  return null;
12494
11625
  }
12495
11626
  for (const artifactDir of resolveTaskArtifactDirs2(projectRoot, taskId3)) {
12496
- const summary = readJsonFile3(resolve24(artifactDir, "validation-summary.json"), null);
11627
+ const summary = readJsonFile3(resolve23(artifactDir, "validation-summary.json"), null);
12497
11628
  if (!summary || summary.status !== "fail") {
12498
11629
  continue;
12499
11630
  }
@@ -12574,9 +11705,9 @@ function readTaskRunAcceptedArtifactState(input) {
12574
11705
  if (!input.taskId || !input.workspaceDir) {
12575
11706
  return { accepted: false, reason: null };
12576
11707
  }
12577
- const artifactDir = resolve24(input.workspaceDir, "artifacts", input.taskId);
12578
- const reviewStatusPath = resolve24(artifactDir, "review-status.txt");
12579
- const taskResultPath = resolve24(artifactDir, "task-result.json");
11708
+ const artifactDir = resolve23(input.workspaceDir, "artifacts", input.taskId);
11709
+ const reviewStatusPath = resolve23(artifactDir, "review-status.txt");
11710
+ const taskResultPath = resolve23(artifactDir, "task-result.json");
12580
11711
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
12581
11712
  if (reviewStatus !== "APPROVED") {
12582
11713
  return { accepted: false, reason: null };
@@ -12613,12 +11744,12 @@ function resolveTaskRunRetryContext(input) {
12613
11744
  if (!input.taskId || !input.workspaceDir) {
12614
11745
  return { shouldRetry: false, failureDetail: null, nextPrompt: null };
12615
11746
  }
12616
- const artifactDir = resolve24(input.workspaceDir, "artifacts", input.taskId);
12617
- const reviewStatePath = resolve24(artifactDir, "review-state.json");
12618
- const reviewFeedbackPath = resolve24(artifactDir, "review-feedback.md");
12619
- const reviewStatusPath = resolve24(artifactDir, "review-status.txt");
12620
- const failedApproachesPath = resolve24(input.workspaceDir, ".rig", "state", "failed_approaches.md");
12621
- const validationSummaryPath = resolve24(artifactDir, "validation-summary.json");
11747
+ const artifactDir = resolve23(input.workspaceDir, "artifacts", input.taskId);
11748
+ const reviewStatePath = resolve23(artifactDir, "review-state.json");
11749
+ const reviewFeedbackPath = resolve23(artifactDir, "review-feedback.md");
11750
+ const reviewStatusPath = resolve23(artifactDir, "review-status.txt");
11751
+ const failedApproachesPath = resolve23(input.workspaceDir, ".rig", "state", "failed_approaches.md");
11752
+ const validationSummaryPath = resolve23(artifactDir, "validation-summary.json");
12622
11753
  const reviewState = readJsonFile3(reviewStatePath, null);
12623
11754
  const reviewStatus = readTaskRunReviewStatus(reviewStatusPath);
12624
11755
  const reviewRejected = isTaskRunReviewRejected(reviewState);
@@ -13028,15 +12159,15 @@ async function executeRigOwnedTaskRun(context, input) {
13028
12159
  const loadedAutomationConfig = await loadTaskRunAutomationConfig(context.projectRoot);
13029
12160
  const automationConfig = input.prMode ? { ...loadedAutomationConfig ?? {}, pr: { ...loadedAutomationConfig?.pr ?? {}, mode: input.prMode } } : loadedAutomationConfig;
13030
12161
  const planningClassification = classifyPlanningNeed({ config: automationConfig, sourceTask });
13031
- const planningArtifactPath = resolve24("artifacts", runtimeTaskId, "implementation-plan.md");
12162
+ const planningArtifactPath = resolve23("artifacts", runtimeTaskId, "implementation-plan.md");
13032
12163
  const persistedPlanning = {
13033
12164
  ...planningClassification,
13034
12165
  classifier: input.runtimeAdapter === "pi" ? "pi-rig-structured-policy" : "rig-structured-policy",
13035
12166
  artifactPath: planningClassification.planningRequired ? planningArtifactPath : null,
13036
12167
  classifiedAt: new Date().toISOString()
13037
12168
  };
13038
- mkdirSync12(resolve24(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
13039
- writeFileSync9(resolve24(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
12169
+ mkdirSync10(resolve23(context.projectRoot, ".rig", "runs", input.runId), { recursive: true });
12170
+ writeFileSync7(resolve23(context.projectRoot, ".rig", "runs", input.runId, "planning-classification.json"), `${JSON.stringify(persistedPlanning, null, 2)}
13040
12171
  `, "utf8");
13041
12172
  patchAuthorityRun(context.projectRoot, input.runId, { planning: persistedPlanning });
13042
12173
  prompt = `${prompt}
@@ -13086,7 +12217,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
13086
12217
  let verificationStarted = false;
13087
12218
  let reviewStarted = false;
13088
12219
  let latestRuntimeWorkspace = resumeMode && typeof existingRunRecord?.worktreePath === "string" ? existingRunRecord.worktreePath : null;
13089
- let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve24(existingRunRecord.sessionPath, "..") : null;
12220
+ let latestSessionDir = resumeMode && typeof existingRunRecord?.sessionPath === "string" ? resolve23(existingRunRecord.sessionPath, "..") : null;
13090
12221
  let latestLogsDir = resumeMode && typeof existingRunRecord?.logRoot === "string" ? existingRunRecord.logRoot : null;
13091
12222
  let latestProviderCommand = null;
13092
12223
  let latestRuntimeBranch = resumeMode && typeof existingRunRecord?.branch === "string" ? existingRunRecord.branch : null;
@@ -13172,10 +12303,10 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
13172
12303
  setRunStatusOrFail(context.projectRoot, input.runId, "running");
13173
12304
  patchAuthorityRun(context.projectRoot, input.runId, {
13174
12305
  worktreePath: latestRuntimeWorkspace,
13175
- artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve24(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
12306
+ artifactRoot: latestRuntimeWorkspace && input.taskId ? resolve23(latestRuntimeWorkspace, "artifacts", input.taskId) : null,
13176
12307
  logRoot: latestLogsDir,
13177
- sessionPath: latestSessionDir ? resolve24(latestSessionDir, "session.json") : null,
13178
- sessionLogPath: latestLogsDir ? resolve24(latestLogsDir, "agent-stdout.log") : null,
12308
+ sessionPath: latestSessionDir ? resolve23(latestSessionDir, "session.json") : null,
12309
+ sessionLogPath: latestLogsDir ? resolve23(latestLogsDir, "agent-stdout.log") : null,
13179
12310
  branch: runtimeId
13180
12311
  });
13181
12312
  if (!dirtyBaselineApplied && input.baselineMode === "dirty-snapshot" && latestRuntimeWorkspace) {
@@ -13183,8 +12314,8 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
13183
12314
  const dirty = applyDirtyBaselineSnapshot({ sourceRoot: context.projectRoot, targetRoot: latestRuntimeWorkspace });
13184
12315
  const readyFile = childEnv.RIG_DIRTY_BASELINE_READY_FILE;
13185
12316
  if (readyFile) {
13186
- mkdirSync12(resolve24(readyFile, ".."), { recursive: true });
13187
- writeFileSync9(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
12317
+ mkdirSync10(resolve23(readyFile, ".."), { recursive: true });
12318
+ writeFileSync7(readyFile, `${JSON.stringify({ ...dirty, workspaceDir: latestRuntimeWorkspace, appliedAt: new Date().toISOString() }, null, 2)}
13188
12319
  `, "utf8");
13189
12320
  }
13190
12321
  appendRunLog(context.projectRoot, input.runId, {
@@ -13580,7 +12711,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
13580
12711
  let acceptedArtifactObservedAt = null;
13581
12712
  let acceptedArtifactPollTimer = null;
13582
12713
  let acceptedArtifactKillTimer = null;
13583
- const attemptExit = await new Promise((resolve25) => {
12714
+ const attemptExit = await new Promise((resolve24) => {
13584
12715
  let settled = false;
13585
12716
  const settle = (result) => {
13586
12717
  if (settled)
@@ -13588,7 +12719,7 @@ ${planningClassification.planningRequired ? `Before implementing, write a concis
13588
12719
  settled = true;
13589
12720
  if (acceptedArtifactPollTimer)
13590
12721
  clearInterval(acceptedArtifactPollTimer);
13591
- resolve25(result);
12722
+ resolve24(result);
13592
12723
  };
13593
12724
  const pollAcceptedArtifacts = () => {
13594
12725
  const artifactState = readTaskRunAcceptedArtifactState({
@@ -13791,7 +12922,7 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
13791
12922
  }
13792
12923
  if (planningClassification.planningRequired) {
13793
12924
  const planWorkspace = latestRuntimeWorkspace ?? context.projectRoot;
13794
- const expectedPlanPath = resolve24(planWorkspace, planningArtifactPath);
12925
+ const expectedPlanPath = resolve23(planWorkspace, planningArtifactPath);
13795
12926
  if (!existsSync16(expectedPlanPath)) {
13796
12927
  const failedAt = new Date().toISOString();
13797
12928
  const failureDetail = `Planning was required (${planningClassification.reason}) but ${planningArtifactPath} was not written before implementation completed.`;
@@ -13961,9 +13092,9 @@ Failed to update task source for ${input.taskId ?? runtimeTaskId} to failed: ${e
13961
13092
  });
13962
13093
  emitServerRunEvent({ type: "log", runId: input.runId, title: "Pi PR feedback fix stderr" });
13963
13094
  });
13964
- const exitCode = await new Promise((resolve25) => {
13965
- child.once("error", () => resolve25(1));
13966
- child.once("close", (code) => resolve25(code ?? 1));
13095
+ const exitCode = await new Promise((resolve24) => {
13096
+ child.once("error", () => resolve24(1));
13097
+ child.once("close", (code) => resolve24(code ?? 1));
13967
13098
  });
13968
13099
  for (const pendingLog of flushPendingClaudeToolUseLogs({
13969
13100
  runId: input.runId,
@@ -14104,8 +13235,8 @@ async function executeTest(context, args) {
14104
13235
  init_runner();
14105
13236
  init__parsers();
14106
13237
  init__paths();
14107
- import { existsSync as existsSync17, mkdirSync as mkdirSync13, readdirSync as readdirSync3, writeFileSync as writeFileSync10 } from "fs";
14108
- import { resolve as resolve25 } from "path";
13238
+ import { existsSync as existsSync17, mkdirSync as mkdirSync11, readdirSync as readdirSync3, writeFileSync as writeFileSync8 } from "fs";
13239
+ import { resolve as resolve24 } from "path";
14109
13240
  import { createPluginHost } from "@rig/core";
14110
13241
  import {
14111
13242
  isSupportedBunVersion as isSupportedBunVersion2,
@@ -14160,12 +13291,12 @@ function runSetupInit(projectRoot) {
14160
13291
  const stateDir = resolveControlPlaneHostStateDir(projectRoot);
14161
13292
  const logsDir = resolveControlPlaneHostLogsDir(projectRoot);
14162
13293
  const artifactsDir = resolveControlPlaneArtifactsDir(projectRoot);
14163
- mkdirSync13(stateDir, { recursive: true });
14164
- mkdirSync13(logsDir, { recursive: true });
14165
- mkdirSync13(artifactsDir, { recursive: true });
14166
- const failuresPath = resolve25(stateDir, "failed_approaches.md");
13294
+ mkdirSync11(stateDir, { recursive: true });
13295
+ mkdirSync11(logsDir, { recursive: true });
13296
+ mkdirSync11(artifactsDir, { recursive: true });
13297
+ const failuresPath = resolve24(stateDir, "failed_approaches.md");
14167
13298
  if (!existsSync17(failuresPath)) {
14168
- writeFileSync10(failuresPath, `# Failed Approaches
13299
+ writeFileSync8(failuresPath, `# Failed Approaches
14169
13300
 
14170
13301
  `, "utf-8");
14171
13302
  }
@@ -14182,17 +13313,17 @@ async function runSetupCheck(projectRoot, outputMode = "text") {
14182
13313
  }
14183
13314
  async function runSetupPreflight(projectRoot, outputMode = "text") {
14184
13315
  await runSetupCheck(projectRoot, outputMode);
14185
- const validationRoot = resolve25(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
13316
+ const validationRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "validation");
14186
13317
  if (existsSync17(validationRoot)) {
14187
13318
  const validators = readdirSync3(validationRoot, { withFileTypes: true }).filter((entry) => entry.isDirectory());
14188
13319
  for (const validator of validators) {
14189
- const script = resolve25(validationRoot, validator.name, "validate.sh");
13320
+ const script = resolve24(validationRoot, validator.name, "validate.sh");
14190
13321
  if (existsSync17(script)) {
14191
13322
  console.log(`OK: validator script ${script}`);
14192
13323
  }
14193
13324
  }
14194
13325
  }
14195
- const hooksRoot = resolve25(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
13326
+ const hooksRoot = resolve24(resolveControlPlaneDefinitionRoot(projectRoot), "hooks");
14196
13327
  if (existsSync17(hooksRoot)) {
14197
13328
  const hooks = readdirSync3(hooksRoot).filter((name) => name.endsWith(".sh"));
14198
13329
  for (const hook of hooks) {
@@ -14339,7 +13470,7 @@ var PROJECT_REQUIRED_GROUPS = new Set([
14339
13470
  ]);
14340
13471
  var RIG_CONFIG_FILENAMES = ["rig.config.ts", "rig.config.mts", "rig.config.json"];
14341
13472
  function hasInitializedRigProject(projectRoot) {
14342
- return RIG_CONFIG_FILENAMES.some((name) => existsSync19(resolve26(projectRoot, name))) || existsSync19(resolve26(projectRoot, ".rig"));
13473
+ return RIG_CONFIG_FILENAMES.some((name) => existsSync19(resolve25(projectRoot, name))) || existsSync19(resolve25(projectRoot, ".rig"));
14343
13474
  }
14344
13475
  function requireInitializedRigProject(context, group) {
14345
13476
  if (hasInitializedRigProject(context.projectRoot)) {
@@ -14393,7 +13524,7 @@ function resolveTopLevelLaunchState(context) {
14393
13524
  let selectedServer = null;
14394
13525
  if (projectInitialized) {
14395
13526
  try {
14396
- const statePath = resolve26(context.projectRoot, ".rig", "state", "connection.json");
13527
+ const statePath = resolve25(context.projectRoot, ".rig", "state", "connection.json");
14397
13528
  if (existsSync19(statePath)) {
14398
13529
  const parsed = JSON.parse(readFileSync13(statePath, "utf-8"));
14399
13530
  selectedServer = parsed.remoteUrl || parsed.url || parsed.selected || null;
@@ -14402,14 +13533,8 @@ function resolveTopLevelLaunchState(context) {
14402
13533
  }
14403
13534
  return { projectInitialized, selectedServer, version: process.env.RIG_CLI_VERSION || readBuildConfig().RIG_CLI_VERSION || undefined };
14404
13535
  }
14405
- function envTruthy(value) {
14406
- if (!value)
14407
- return false;
14408
- const normalized = value.trim().toLowerCase();
14409
- return normalized !== "0" && normalized !== "false" && normalized !== "no";
14410
- }
14411
13536
  function shouldOpenApp(context) {
14412
- 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);
13537
+ return context.outputMode === "text" && Boolean(process.stdin.isTTY && process.stdout.isTTY) && process.env.RIG_CLI_PLAIN_HELP !== "1";
14413
13538
  }
14414
13539
  async function openApp(context, options = {}) {
14415
13540
  const { runOperatorBoardLoop: runOperatorBoardLoop2 } = await Promise.resolve().then(() => (init_board(), exports_board));
@@ -14618,7 +13743,7 @@ var __testOnly = {
14618
13743
  };
14619
13744
  // packages/cli/src/launcher.ts
14620
13745
  import { existsSync as existsSync20 } from "fs";
14621
- import { basename as basename3, resolve as resolve27 } from "path";
13746
+ import { basename as basename3, resolve as resolve26 } from "path";
14622
13747
  import { loadDotEnvSecrets } from "@rig/runtime/baked-secrets";
14623
13748
  import { RIG_DEFINITION_DIRNAME, RIG_STATE_DIRNAME, resolveNearestRigProjectRoot } from "@rig/runtime/layout";
14624
13749
 
@@ -14630,9 +13755,7 @@ import {
14630
13755
  RigInboxInputsOutput,
14631
13756
  RigRunListOutput,
14632
13757
  RigRunShowOutput,
14633
- RigServerRepairLinkOutput,
14634
13758
  RigServerStatusOutput,
14635
- RigServerUseOutput,
14636
13759
  RigStatsOutput,
14637
13760
  RigTaskListOutput,
14638
13761
  RigTaskShowOutput
@@ -14642,9 +13765,7 @@ var CLI_OUTPUT_SCHEMAS = {
14642
13765
  "task show": RigTaskShowOutput,
14643
13766
  "run list": RigRunListOutput,
14644
13767
  "run show": RigRunShowOutput,
14645
- "server use": RigServerUseOutput,
14646
13768
  "server status": RigServerStatusOutput,
14647
- "server repair-link": RigServerRepairLinkOutput,
14648
13769
  "inbox approvals": RigInboxApprovalsOutput,
14649
13770
  "inbox inputs": RigInboxInputsOutput,
14650
13771
  "doctor check": RigDoctorCheckOutput,
@@ -14686,7 +13807,7 @@ function parsePolicyMode(value) {
14686
13807
  throw new Error(`Invalid --policy-mode value: ${value}. Use off|observe|enforce.`);
14687
13808
  }
14688
13809
  function hasRigProjectMarker(candidate) {
14689
- 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"));
13810
+ 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"));
14690
13811
  }
14691
13812
  function resolveProjectRoot({
14692
13813
  envProjectRoot,
@@ -14695,19 +13816,19 @@ function resolveProjectRoot({
14695
13816
  cwd = process.cwd()
14696
13817
  }) {
14697
13818
  if (envProjectRoot) {
14698
- return resolve27(cwd, envProjectRoot);
13819
+ return resolve26(cwd, envProjectRoot);
14699
13820
  }
14700
13821
  const fallbackImportDir = importDir ?? cwd;
14701
13822
  const execName = basename3(execPath).toLowerCase();
14702
- const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve27(execPath, "..", "..")] : [];
14703
- const candidates = [cwd, ...execCandidates, resolve27(fallbackImportDir, "..")];
13823
+ const execCandidates = execName === "rig" || execName === "rig.exe" ? [resolve26(execPath, "..", "..")] : [];
13824
+ const candidates = [cwd, ...execCandidates, resolve26(fallbackImportDir, "..")];
14704
13825
  for (const candidate of candidates) {
14705
13826
  const nearest = resolveNearestRigProjectRoot(candidate);
14706
13827
  if (hasRigProjectMarker(nearest)) {
14707
13828
  return nearest;
14708
13829
  }
14709
13830
  }
14710
- return resolve27(cwd);
13831
+ return resolve26(cwd);
14711
13832
  }
14712
13833
  function normalizeCliErrorCode(message2, isCliError) {
14713
13834
  if (message2.startsWith("Invalid --policy-mode value:")) {
@@ -14781,7 +13902,7 @@ async function runRigCli(module, options = {}) {
14781
13902
  runId: context.runId,
14782
13903
  outcome,
14783
13904
  eventsFile: context.eventBus.getEventsFile(),
14784
- policyFile: resolve27(projectRoot, "rig", "policy", "policy.json"),
13905
+ policyFile: resolve26(projectRoot, "rig", "policy", "policy.json"),
14785
13906
  policyMode: context.policyMode ?? policyMode ?? module.loadPolicy(projectRoot).mode
14786
13907
  }, null, 2));
14787
13908
  }