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

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 (163) hide show
  1. package/dist/bin/rig.js +22060 -14620
  2. package/dist/src/app/board.js +155 -28
  3. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
  4. package/dist/src/app-opentui/adapters/doctor.js +1 -25
  5. package/dist/src/app-opentui/adapters/family.d.ts +62 -0
  6. package/dist/src/app-opentui/adapters/family.js +14305 -0
  7. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
  8. package/dist/src/app-opentui/adapters/fleet.js +6 -40
  9. package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
  10. package/dist/src/app-opentui/adapters/inbox.js +54 -59
  11. package/dist/src/app-opentui/adapters/init.d.ts +0 -2
  12. package/dist/src/app-opentui/adapters/init.js +0 -26
  13. package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
  14. package/dist/src/app-opentui/adapters/inspect.js +1024 -0
  15. package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
  16. package/dist/src/app-opentui/adapters/pi-attach.js +348 -93
  17. package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
  18. package/dist/src/app-opentui/adapters/pi.js +363 -0
  19. package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
  20. package/dist/src/app-opentui/adapters/plugin.js +544 -0
  21. package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
  22. package/dist/src/app-opentui/adapters/repo.js +186 -0
  23. package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
  24. package/dist/src/app-opentui/adapters/run-detail.js +97 -44
  25. package/dist/src/app-opentui/adapters/server.d.ts +10 -2
  26. package/dist/src/app-opentui/adapters/server.js +96 -27
  27. package/dist/src/app-opentui/adapters/tasks.d.ts +0 -2
  28. package/dist/src/app-opentui/adapters/tasks.js +437 -105
  29. package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
  30. package/dist/src/app-opentui/adapters/workspace.js +333 -0
  31. package/dist/src/app-opentui/autocomplete.d.ts +20 -0
  32. package/dist/src/app-opentui/autocomplete.js +576 -0
  33. package/dist/src/app-opentui/bootstrap.js +24313 -16963
  34. package/dist/src/app-opentui/command-palette.d.ts +3 -0
  35. package/dist/src/app-opentui/command-palette.js +1010 -0
  36. package/dist/src/app-opentui/drone.js +8 -6
  37. package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
  38. package/dist/src/app-opentui/fleet-stats.js +114 -0
  39. package/dist/src/app-opentui/index.js +3438 -1724
  40. package/dist/src/app-opentui/intent.js +71 -48
  41. package/dist/src/app-opentui/keymap.d.ts +6 -5
  42. package/dist/src/app-opentui/keymap.js +1064 -23
  43. package/dist/src/app-opentui/layout.d.ts +7 -0
  44. package/dist/src/app-opentui/layout.js +13 -6
  45. package/dist/src/app-opentui/list-search.d.ts +24 -0
  46. package/dist/src/app-opentui/list-search.js +88 -1
  47. package/dist/src/app-opentui/pi-host-child.js +33 -1
  48. package/dist/src/app-opentui/pi-pty-host.d.ts +5 -0
  49. package/dist/src/app-opentui/pi-pty-host.js +21 -3
  50. package/dist/src/app-opentui/react/App.d.ts +9 -0
  51. package/dist/src/app-opentui/react/App.js +5099 -0
  52. package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
  53. package/dist/src/app-opentui/react/Backdrop.js +829 -0
  54. package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
  55. package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
  56. package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
  57. package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
  58. package/dist/src/app-opentui/react/context.d.ts +17 -0
  59. package/dist/src/app-opentui/react/context.js +37 -0
  60. package/dist/src/app-opentui/react/launch.d.ts +2 -0
  61. package/dist/src/app-opentui/react/launch.js +5698 -0
  62. package/dist/src/app-opentui/react/nav.d.ts +18 -0
  63. package/dist/src/app-opentui/react/nav.js +54 -0
  64. package/dist/src/app-opentui/react/scroll.d.ts +12 -0
  65. package/dist/src/app-opentui/react/scroll.js +21 -0
  66. package/dist/src/app-opentui/react/syntax.d.ts +2 -0
  67. package/dist/src/app-opentui/react/syntax.js +64 -0
  68. package/dist/src/app-opentui/registry.js +19923 -5151
  69. package/dist/src/app-opentui/render/constants.d.ts +31 -0
  70. package/dist/src/app-opentui/render/constants.js +66 -0
  71. package/dist/src/app-opentui/render/graphics.d.ts +2 -1
  72. package/dist/src/app-opentui/render/graphics.js +106 -39
  73. package/dist/src/app-opentui/render/image-visual-layer-worker.js +108 -20
  74. package/dist/src/app-opentui/render/image-visual-layer.d.ts +7 -0
  75. package/dist/src/app-opentui/render/image-visual-layer.js +109 -20
  76. package/dist/src/app-opentui/render/native-host.d.ts +37 -0
  77. package/dist/src/app-opentui/render/native-host.js +179 -0
  78. package/dist/src/app-opentui/render/panels.js +18 -11
  79. package/dist/src/app-opentui/render/preloader.js +8 -6
  80. package/dist/src/app-opentui/render/scene.d.ts +50 -1
  81. package/dist/src/app-opentui/render/scene.js +183 -6
  82. package/dist/src/app-opentui/render/text.d.ts +7 -1
  83. package/dist/src/app-opentui/render/text.js +10 -7
  84. package/dist/src/app-opentui/render/type-bar.js +69 -30
  85. package/dist/src/app-opentui/runtime.d.ts +44 -1
  86. package/dist/src/app-opentui/runtime.js +3231 -1363
  87. package/dist/src/app-opentui/scenes/command.js +20 -6
  88. package/dist/src/app-opentui/scenes/doctor.js +176 -11
  89. package/dist/src/app-opentui/scenes/error.js +20 -10
  90. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
  91. package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
  92. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
  93. package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
  94. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
  95. package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
  96. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
  97. package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
  98. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
  99. package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
  100. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
  101. package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
  102. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
  103. package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
  104. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
  105. package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
  106. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
  107. package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
  108. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
  109. package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
  110. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
  111. package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
  112. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
  113. package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
  114. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
  115. package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
  116. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
  117. package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
  118. package/dist/src/app-opentui/scenes/family.d.ts +3 -0
  119. package/dist/src/app-opentui/scenes/family.js +2144 -0
  120. package/dist/src/app-opentui/scenes/fleet.js +521 -31
  121. package/dist/src/app-opentui/scenes/handoff.js +204 -12
  122. package/dist/src/app-opentui/scenes/help.js +609 -40
  123. package/dist/src/app-opentui/scenes/inbox.js +278 -17
  124. package/dist/src/app-opentui/scenes/init.js +84 -39
  125. package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
  126. package/dist/src/app-opentui/scenes/inspect.js +793 -0
  127. package/dist/src/app-opentui/scenes/main.js +218 -39
  128. package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
  129. package/dist/src/app-opentui/scenes/pi.js +508 -0
  130. package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
  131. package/dist/src/app-opentui/scenes/plugin.js +486 -0
  132. package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
  133. package/dist/src/app-opentui/scenes/repo.js +424 -0
  134. package/dist/src/app-opentui/scenes/run-detail.js +333 -20
  135. package/dist/src/app-opentui/scenes/server.js +181 -15
  136. package/dist/src/app-opentui/scenes/tasks.js +486 -31
  137. package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
  138. package/dist/src/app-opentui/scenes/workspace.js +426 -0
  139. package/dist/src/app-opentui/selectable.d.ts +19 -0
  140. package/dist/src/app-opentui/selectable.js +79 -0
  141. package/dist/src/app-opentui/state.js +83 -30
  142. package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
  143. package/dist/src/app-opentui/surface-catalog.js +540 -0
  144. package/dist/src/app-opentui/theme.d.ts +28 -6
  145. package/dist/src/app-opentui/theme.js +61 -8
  146. package/dist/src/app-opentui/types.d.ts +121 -4
  147. package/dist/src/commands/_authority-runs.d.ts +1 -1
  148. package/dist/src/commands/_authority-runs.js +2 -12
  149. package/dist/src/commands/_help-catalog.js +95 -15
  150. package/dist/src/commands/_operator-view.js +34 -2
  151. package/dist/src/commands/_pi-frontend.d.ts +2 -0
  152. package/dist/src/commands/_pi-frontend.js +34 -0
  153. package/dist/src/commands/_server-events.d.ts +26 -0
  154. package/dist/src/commands/_server-events.js +310 -0
  155. package/dist/src/commands/agent.js +2 -12
  156. package/dist/src/commands/run.js +34 -2
  157. package/dist/src/commands/server.js +2 -12
  158. package/dist/src/commands/stats.js +95 -15
  159. package/dist/src/commands/task-run-driver.js +2 -12
  160. package/dist/src/commands/task.js +131 -29
  161. package/dist/src/commands.js +192 -31
  162. package/dist/src/index.js +192 -31
  163. package/package.json +11 -9
@@ -0,0 +1,310 @@
1
+ // @bun
2
+ // packages/cli/src/commands/_server-events.ts
3
+ import { WsTransport } from "@rig/client";
4
+ import { RIG_WS_CHANNELS } from "@rig/contracts";
5
+
6
+ // packages/cli/src/commands/_server-client.ts
7
+ import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
8
+ import { resolve as resolve2 } from "path";
9
+
10
+ // packages/cli/src/runner.ts
11
+ import { EventBus } from "@rig/runtime/control-plane/runtime/events";
12
+ import { CliError as RuntimeCliError } from "@rig/runtime/control-plane/errors";
13
+ import { evaluate, loadPolicy, resolveAction } from "@rig/runtime/control-plane/runtime/guard";
14
+ import { buildBinary } from "@rig/runtime/control-plane/runtime/isolation";
15
+
16
+ class CliError extends RuntimeCliError {
17
+ hint;
18
+ constructor(message, exitCode = 1, options = {}) {
19
+ super(message, exitCode);
20
+ if (options.hint?.trim()) {
21
+ this.hint = options.hint.trim();
22
+ }
23
+ }
24
+ }
25
+
26
+ // packages/cli/src/commands/_server-client.ts
27
+ import { ensureLocalRigServerConnection } from "@rig/runtime/local-server";
28
+
29
+ // packages/cli/src/commands/_connection-state.ts
30
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
31
+ import { homedir } from "os";
32
+ import { dirname, resolve } from "path";
33
+ function resolveGlobalConnectionsPath(env = process.env) {
34
+ const explicit = env.RIG_CONNECTIONS_FILE?.trim();
35
+ if (explicit)
36
+ return resolve(explicit);
37
+ const stateDir = env.RIG_GLOBAL_STATE_DIR?.trim();
38
+ if (stateDir)
39
+ return resolve(stateDir, "connections.json");
40
+ return resolve(homedir(), ".rig", "connections.json");
41
+ }
42
+ function resolveRepoConnectionPath(projectRoot) {
43
+ return resolve(projectRoot, ".rig", "state", "connection.json");
44
+ }
45
+ function readJsonFile(path) {
46
+ if (!existsSync(path))
47
+ return null;
48
+ try {
49
+ return JSON.parse(readFileSync(path, "utf8"));
50
+ } catch (error) {
51
+ throw new CliError(`Invalid Rig connection state at ${path}: ${error instanceof Error ? error.message : String(error)}`, 1, { hint: "Fix or delete that file, then re-select a server with `rig server use <alias|local>`." });
52
+ }
53
+ }
54
+ function writeJsonFile(path, value) {
55
+ mkdirSync(dirname(path), { recursive: true });
56
+ writeFileSync(path, `${JSON.stringify(value, null, 2)}
57
+ `, "utf8");
58
+ }
59
+ function normalizeConnection(value) {
60
+ if (!value || typeof value !== "object" || Array.isArray(value))
61
+ return null;
62
+ const record = value;
63
+ if (record.kind === "local")
64
+ return { kind: "local", mode: "auto" };
65
+ if (record.kind === "remote" && typeof record.baseUrl === "string" && record.baseUrl.trim()) {
66
+ const baseUrl = record.baseUrl.trim().replace(/\/+$/, "");
67
+ return { kind: "remote", baseUrl };
68
+ }
69
+ return null;
70
+ }
71
+ function readGlobalConnections(options = {}) {
72
+ const path = resolveGlobalConnectionsPath(options.env ?? process.env);
73
+ const payload = readJsonFile(path);
74
+ if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
75
+ return { connections: {} };
76
+ }
77
+ const rawConnections = payload.connections;
78
+ const connections = {};
79
+ if (rawConnections && typeof rawConnections === "object" && !Array.isArray(rawConnections)) {
80
+ for (const [alias, raw] of Object.entries(rawConnections)) {
81
+ const connection = normalizeConnection(raw);
82
+ if (connection)
83
+ connections[alias] = connection;
84
+ }
85
+ }
86
+ return { connections };
87
+ }
88
+ function readRepoConnection(projectRoot) {
89
+ const payload = readJsonFile(resolveRepoConnectionPath(projectRoot));
90
+ if (!payload || typeof payload !== "object" || Array.isArray(payload))
91
+ return null;
92
+ const record = payload;
93
+ const selected = typeof record.selected === "string" ? record.selected.trim() : "";
94
+ if (!selected)
95
+ return null;
96
+ return {
97
+ selected,
98
+ project: typeof record.project === "string" ? record.project : undefined,
99
+ linkedAt: typeof record.linkedAt === "string" ? record.linkedAt : undefined,
100
+ serverProjectRoot: typeof record.serverProjectRoot === "string" && record.serverProjectRoot.trim() ? record.serverProjectRoot.trim() : undefined
101
+ };
102
+ }
103
+ function writeRepoConnection(projectRoot, state) {
104
+ writeJsonFile(resolveRepoConnectionPath(projectRoot), state);
105
+ }
106
+ function resolveSelectedConnection(projectRoot, options = {}) {
107
+ const repo = readRepoConnection(projectRoot);
108
+ if (!repo)
109
+ return null;
110
+ if (repo.selected === "local")
111
+ return { alias: "local", connection: { kind: "local", mode: "auto" }, serverProjectRoot: repo.serverProjectRoot };
112
+ const global = readGlobalConnections(options);
113
+ const connection = global.connections[repo.selected];
114
+ if (!connection) {
115
+ throw new CliError(`Selected Rig server "${repo.selected}" was not found. Run \`rig server list\` or \`rig server use local\`.`, 1);
116
+ }
117
+ return { alias: repo.selected, connection, serverProjectRoot: repo.serverProjectRoot };
118
+ }
119
+ function writeRepoServerProjectRoot(projectRoot, serverProjectRoot) {
120
+ const repo = readRepoConnection(projectRoot);
121
+ if (!repo)
122
+ return;
123
+ writeRepoConnection(projectRoot, { ...repo, serverProjectRoot });
124
+ }
125
+
126
+ // packages/cli/src/commands/_server-client.ts
127
+ var scopedGitHubBearerTokens = new Map;
128
+ var serverPhaseListener = null;
129
+ function reportServerPhase(label) {
130
+ serverPhaseListener?.(label);
131
+ }
132
+ function cleanToken(value) {
133
+ const trimmed = value?.trim();
134
+ return trimmed ? trimmed : null;
135
+ }
136
+ function readRemoteAuthState(projectRoot) {
137
+ const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
138
+ if (!existsSync2(path))
139
+ return null;
140
+ try {
141
+ const parsed = JSON.parse(readFileSync2(path, "utf8"));
142
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
143
+ } catch {
144
+ return null;
145
+ }
146
+ }
147
+ function readPrivateRemoteSessionToken(projectRoot) {
148
+ const parsed = readRemoteAuthState(projectRoot);
149
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
150
+ }
151
+ function readGitHubBearerTokenForRemote(projectRoot) {
152
+ const scopedKey = resolve2(projectRoot);
153
+ if (scopedGitHubBearerTokens.has(scopedKey))
154
+ return scopedGitHubBearerTokens.get(scopedKey) ?? null;
155
+ const privateSession = readPrivateRemoteSessionToken(projectRoot);
156
+ if (privateSession)
157
+ return privateSession;
158
+ return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
159
+ }
160
+ function readStoredGitHubAuthToken(projectRoot) {
161
+ const parsed = readRemoteAuthState(projectRoot);
162
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
163
+ }
164
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
165
+ const repo = readRepoConnection(projectRoot);
166
+ const slug = repo?.project?.trim();
167
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
168
+ return null;
169
+ const auth = readRemoteAuthState(projectRoot);
170
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
171
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
172
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
173
+ return null;
174
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
175
+ if (!checkoutBaseDir)
176
+ return null;
177
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
178
+ writeRepoServerProjectRoot(projectRoot, inferred);
179
+ return inferred;
180
+ }
181
+ function readLocalConnectionFallbackToken(projectRoot) {
182
+ return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
183
+ }
184
+ async function ensureServerForCli(projectRoot) {
185
+ try {
186
+ const selected = resolveSelectedConnection(projectRoot);
187
+ if (selected?.connection.kind === "remote") {
188
+ reportServerPhase(`Connecting to ${selected.alias}\u2026`);
189
+ const authToken = readGitHubBearerTokenForRemote(projectRoot);
190
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
191
+ return {
192
+ baseUrl: selected.connection.baseUrl,
193
+ authToken,
194
+ connectionKind: "remote",
195
+ serverProjectRoot
196
+ };
197
+ }
198
+ reportServerPhase("Starting local Rig server\u2026");
199
+ const connection = await ensureLocalRigServerConnection(projectRoot);
200
+ return {
201
+ baseUrl: connection.baseUrl,
202
+ authToken: connection.authToken ?? readLocalConnectionFallbackToken(projectRoot),
203
+ connectionKind: "local",
204
+ serverProjectRoot: resolve2(projectRoot)
205
+ };
206
+ } catch (error) {
207
+ if (error instanceof Error) {
208
+ throw new CliError(error.message, 1);
209
+ }
210
+ throw error;
211
+ }
212
+ }
213
+ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken) {
214
+ const repo = readRepoConnection(projectRoot);
215
+ const slug = repo?.project?.trim();
216
+ if (!slug)
217
+ return null;
218
+ try {
219
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
220
+ if (authToken && queryAuthFallbackEnabled())
221
+ url.searchParams.set("rt", authToken);
222
+ const response = await fetch(url, {
223
+ headers: mergeHeaders(undefined, authToken)
224
+ });
225
+ if (!response.ok)
226
+ return null;
227
+ const payload = await response.json();
228
+ const project = payload.project && typeof payload.project === "object" && !Array.isArray(payload.project) ? payload.project : null;
229
+ const checkouts = Array.isArray(project?.checkouts) ? project.checkouts : [];
230
+ const latestCheckout = [...checkouts].reverse().find((entry) => Boolean(entry && typeof entry === "object" && !Array.isArray(entry) && typeof entry.path === "string"));
231
+ const path = typeof latestCheckout?.path === "string" && latestCheckout.path.trim() ? latestCheckout.path.trim() : null;
232
+ if (path)
233
+ writeRepoServerProjectRoot(projectRoot, path);
234
+ return path;
235
+ } catch {
236
+ return null;
237
+ }
238
+ }
239
+ function mergeCookie(existing, name, value) {
240
+ const encoded = `${name}=${encodeURIComponent(value)}`;
241
+ if (!existing?.trim())
242
+ return encoded;
243
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
244
+ return [...parts, encoded].join("; ");
245
+ }
246
+ function queryAuthFallbackEnabled(env = process.env) {
247
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
248
+ }
249
+ function mergeHeaders(headers, authToken) {
250
+ const merged = new Headers(headers);
251
+ if (authToken) {
252
+ const bearer = `Bearer ${authToken}`;
253
+ merged.set("authorization", bearer);
254
+ merged.set("x-auth", bearer);
255
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
256
+ }
257
+ return merged;
258
+ }
259
+ var serverReachabilityCache = new Map;
260
+ var RESUMABLE_RUN_STATUSES = new Set([
261
+ "created",
262
+ "preparing",
263
+ "running",
264
+ "validating",
265
+ "reviewing",
266
+ "stopped",
267
+ "failed",
268
+ "needs-attention",
269
+ "needs_attention"
270
+ ]);
271
+
272
+ // packages/cli/src/commands/_server-events.ts
273
+ function buildRigWebSocketUrl(baseUrl, authToken) {
274
+ const url = new URL(baseUrl);
275
+ url.protocol = url.protocol === "https:" ? "wss:" : "ws:";
276
+ if (authToken)
277
+ url.searchParams.set("token", authToken);
278
+ return url.toString();
279
+ }
280
+ async function connectRigServerEvents(projectRoot, handlers) {
281
+ const { baseUrl, authToken } = await ensureServerForCli(projectRoot);
282
+ const transport = new WsTransport(buildRigWebSocketUrl(baseUrl, authToken));
283
+ const unsubscribers = [];
284
+ if (handlers.onSnapshotInvalidated)
285
+ unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.snapshotInvalidated, handlers.onSnapshotInvalidated));
286
+ if (handlers.onRunLogAppended)
287
+ unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.runLogAppended, handlers.onRunLogAppended));
288
+ if (handlers.onEngineEvent)
289
+ unsubscribers.push(transport.subscribe(RIG_WS_CHANNELS.event, handlers.onEngineEvent));
290
+ let status = "connecting";
291
+ unsubscribers.push(transport.subscribeState((state) => {
292
+ status = state.status;
293
+ handlers.onStatus?.(state.status);
294
+ }));
295
+ return {
296
+ connected: () => status === "connected",
297
+ close: () => {
298
+ for (const unsubscribe of unsubscribers) {
299
+ try {
300
+ unsubscribe();
301
+ } catch {}
302
+ }
303
+ transport.dispose();
304
+ }
305
+ };
306
+ }
307
+ export {
308
+ connectRigServerEvents,
309
+ buildRigWebSocketUrl
310
+ };
@@ -82,18 +82,8 @@ function resolveControlPlaneMonorepoRoot(projectRoot) {
82
82
 
83
83
  // packages/cli/src/commands/_authority-runs.ts
84
84
  var RIG_WORKSPACE_ID = "rig-local-workspace";
85
- function normalizeRuntimeAdapter(value) {
86
- const normalized = value?.trim().toLowerCase();
87
- if (!normalized) {
88
- return "pi";
89
- }
90
- if (normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "gpt-codex") {
91
- return "codex";
92
- }
93
- if (normalized === "pi" || normalized === "rig-pi" || normalized === "@rig/pi") {
94
- return "pi";
95
- }
96
- return "claude-code";
85
+ function normalizeRuntimeAdapter(_value) {
86
+ return "pi";
97
87
  }
98
88
  function readLatestBeadRecord(projectRoot, taskId) {
99
89
  const issuesPath = resolve(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
@@ -1057,6 +1057,14 @@ async function withSpinner(label, work, options = {}) {
1057
1057
  }
1058
1058
 
1059
1059
  // packages/cli/src/commands/_pi-frontend.ts
1060
+ var TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
1061
+
1062
+ class OperatorTranscriptUnavailableError extends Error {
1063
+ constructor(message) {
1064
+ super(message);
1065
+ this.name = "OperatorTranscriptUnavailableError";
1066
+ }
1067
+ }
1060
1068
  function setTemporaryEnv(updates) {
1061
1069
  const previous = new Map;
1062
1070
  for (const [key, value] of Object.entries(updates)) {
@@ -1084,6 +1092,23 @@ function buildOperatorPiEnv(input) {
1084
1092
  ...input.serverProjectRoot ? { RIG_PROJECT_ROOT: input.serverProjectRoot } : {}
1085
1093
  };
1086
1094
  }
1095
+ function shouldRequireOperatorTranscript(status) {
1096
+ return typeof status === "string" && TERMINAL_RUN_STATUSES.has(status.trim().toLowerCase());
1097
+ }
1098
+ function missingOperatorTranscriptMessage(runId, status) {
1099
+ const shortRun = runId.trim().slice(0, 8) || "unknown";
1100
+ const statusText = typeof status === "string" && status.trim() ? status.trim() : "terminal";
1101
+ 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.`;
1102
+ }
1103
+ function statusFromRunDetails(run) {
1104
+ if (!run || typeof run !== "object" || Array.isArray(run))
1105
+ return;
1106
+ const record = run;
1107
+ if (typeof record.status === "string")
1108
+ return record.status;
1109
+ const nested = record.run;
1110
+ return nested && typeof nested === "object" && !Array.isArray(nested) ? nested.status : undefined;
1111
+ }
1087
1112
  async function prepareOperatorConsole(context, runId, tempSessionDir) {
1088
1113
  const server = await ensureServerForCli(context.projectRoot);
1089
1114
  const localCwd = join2(homedir2(), ".rig", "drones", runId.slice(0, 8));
@@ -1113,6 +1138,13 @@ async function prepareOperatorConsole(context, runId, tempSessionDir) {
1113
1138
  sessionFileArg = ["--session", localSessionPath];
1114
1139
  }
1115
1140
  } catch {}
1141
+ if (sessionFileArg.length === 0) {
1142
+ const run = await getRunDetailsViaServer(context, runId).catch(() => null);
1143
+ const status = statusFromRunDetails(run);
1144
+ if (shouldRequireOperatorTranscript(status)) {
1145
+ throw new OperatorTranscriptUnavailableError(missingOperatorTranscriptMessage(runId, status));
1146
+ }
1147
+ }
1116
1148
  return { server, sessionFileArg };
1117
1149
  }
1118
1150
  var RIG_PI_THEME = {
@@ -1260,7 +1292,7 @@ async function attachRunBundledPiFrontend(context, input) {
1260
1292
  }
1261
1293
 
1262
1294
  // packages/cli/src/commands/_operator-view.ts
1263
- var TERMINAL_RUN_STATUSES = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
1295
+ var TERMINAL_RUN_STATUSES2 = new Set(["completed", "failed", "stopped", "cancelled", "canceled", "closed", "merged", "needs_attention", "needs-attention"]);
1264
1296
  function runStatusFromPayload(payload) {
1265
1297
  const run = payload.run && typeof payload.run === "object" && !Array.isArray(payload.run) ? payload.run : payload;
1266
1298
  return String(run.status ?? "unknown").toLowerCase();
@@ -1338,7 +1370,7 @@ async function attachRunOperatorView(context, input) {
1338
1370
  }
1339
1371
  const pollMs = Math.max(250, Math.trunc(input.pollMs ?? 2000));
1340
1372
  let timelineCursor = snapshot.timelineCursor;
1341
- while (!detached && !TERMINAL_RUN_STATUSES.has(runStatusFromPayload(snapshot.run))) {
1373
+ while (!detached && !TERMINAL_RUN_STATUSES2.has(runStatusFromPayload(snapshot.run))) {
1342
1374
  await Bun.sleep(pollMs);
1343
1375
  snapshot = await readOperatorSnapshot(context, input.runId, { timelineCursor });
1344
1376
  timelineCursor = snapshot.timelineCursor;
@@ -55,18 +55,8 @@ import {
55
55
  import { resolveMonorepoRoot } from "@rig/runtime/control-plane/native/utils";
56
56
 
57
57
  // packages/cli/src/commands/_authority-runs.ts
58
- function normalizeRuntimeAdapter(value) {
59
- const normalized = value?.trim().toLowerCase();
60
- if (!normalized) {
61
- return "pi";
62
- }
63
- if (normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "gpt-codex") {
64
- return "codex";
65
- }
66
- if (normalized === "pi" || normalized === "rig-pi" || normalized === "@rig/pi") {
67
- return "pi";
68
- }
69
- return "claude-code";
58
+ function normalizeRuntimeAdapter(_value) {
59
+ return "pi";
70
60
  }
71
61
 
72
62
  // packages/cli/src/app/drone-ui.ts
@@ -889,30 +889,62 @@ var PRIMARY_GROUPS = [
889
889
  }
890
890
  ];
891
891
  var ADVANCED_GROUPS = [
892
- { name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
893
- { name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
892
+ {
893
+ name: "setup",
894
+ summary: "Bootstrap/check local setup.",
895
+ usage: ["rig setup <bootstrap|check|preflight>"],
896
+ commands: [
897
+ { command: "bootstrap", description: "Bootstrap local setup dependencies.", primary: true },
898
+ { command: "check", description: "Check local setup state (toolchain, deps, config).", primary: true },
899
+ { command: "preflight", description: "Run preflight checks before a run.", primary: true }
900
+ ]
901
+ },
902
+ {
903
+ name: "profile",
904
+ summary: "Runtime profile/model defaults.",
905
+ usage: ["rig profile <show|set>"],
906
+ commands: [
907
+ { command: "show", description: "Show the active execution profile.", primary: true },
908
+ { command: "set [--model <model>] [--runtime <runtime>] [--plugin <plugin>]", description: "Set model/runtime/plugin profile defaults.", primary: true }
909
+ ]
910
+ },
894
911
  {
895
912
  name: "review",
896
913
  summary: "Inspect or change completion review gate policy.",
897
914
  usage: ["rig review <show|set>"],
898
915
  commands: [
899
916
  { command: "show", description: "Show current review gate settings." },
900
- { command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider." }
917
+ { command: "set <off|advisory|required> [--provider <provider>]", description: "Change review strictness/provider (e.g. --provider greptile)." }
901
918
  ],
902
919
  examples: ["rig review show", "rig review set required --provider greptile"],
903
920
  next: ["Use `rig inbox approvals` for blocked run handoffs."]
904
921
  },
905
922
  {
906
923
  name: "browser",
907
- summary: "Browser/app diagnostics for browser-required tasks.",
908
- usage: ["rig browser <help|explain|demo|app|hp-next> [options]"],
924
+ summary: "Browser workstation actions for browser-required tasks: launch, check, CDP probe, profile reset, and app-specific smokes.",
925
+ usage: ["rig browser <help|explain|demo|hp-next|cdp-probe|profile-persistence|profile-lock-check|smoke-test> [options]"],
909
926
  commands: [
910
- { command: "help", description: "Rich browser command help (canonical: `rig browser help`)." },
911
- { command: "explain", description: "Explain the browser-required task contract." },
912
- { command: "demo", description: "Run browser demo flows against a local page." },
913
- { command: "app", description: "Launch the Rig Browser workstation app." },
914
- { command: "hp-next <dev|check|e2e|reset>", description: "Drive the hp-next browser test harness." }
915
- ]
927
+ { command: "help", description: "Rich browser command help (canonical: `rig browser help`).", primary: true },
928
+ { command: "explain", description: "Explain the browser-required task contract and runtime helper commands.", primary: true },
929
+ { 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 },
930
+ { command: "hp-next dev", description: "Start hp-next Rig Browser in dev/watch mode.", primary: true },
931
+ { command: "hp-next start", description: "Build/start the hp-next browser workstation without watch mode.", primary: true },
932
+ { command: "hp-next check", description: "Validate the hp-next CDP endpoint on the configured port.", primary: true },
933
+ { command: "hp-next e2e", description: "Run hp-next browser e2e smoke checks through Rig Browser.", primary: true },
934
+ { command: "hp-next reset", description: "Reset the hp-next browser profile when stale browser state is suspected.", primary: true },
935
+ { command: "cdp-probe", description: "Run an isolated CDP attach/evaluate/layout probe." },
936
+ { command: "profile-persistence", description: "Verify a named browser profile persists browser state." },
937
+ { command: "profile-lock-check", description: "Verify concurrent launches reject the same profile." },
938
+ { command: "smoke-test", description: "Run the browser package smoke test." }
939
+ ],
940
+ examples: [
941
+ "rig browser help",
942
+ "rig browser hp-next check",
943
+ "rig browser hp-next e2e",
944
+ "rig browser cdp-probe",
945
+ "rig browser profile-lock-check"
946
+ ],
947
+ next: ["Inside a task run, use rig-browser-launch, rig-browser-check, and rig-browser-attach-info from the worker PATH."]
916
948
  },
917
949
  {
918
950
  name: "pi",
@@ -927,12 +959,60 @@ var ADVANCED_GROUPS = [
927
959
  examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
928
960
  next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
929
961
  },
930
- { name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
931
- { name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
962
+ {
963
+ name: "queue",
964
+ summary: "Run task queues locally.",
965
+ usage: ["rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]"],
966
+ commands: [
967
+ { 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 }
968
+ ]
969
+ },
970
+ {
971
+ name: "agent",
972
+ summary: "Runtime agent workspace helpers.",
973
+ usage: ["rig agent <list|prepare|run|cleanup>"],
974
+ commands: [
975
+ { command: "list", description: "List prepared agent runtimes.", primary: true },
976
+ { command: "prepare [--id <id>] [--mode <mode>] [--task <task>]", description: "Prepare an isolated agent runtime workspace.", primary: true },
977
+ { command: "run [--id <id>] [--mode <mode>] [--task <task>] [--skip-project-sync]", description: "Prepare (if needed) and run an agent in its workspace.", primary: true },
978
+ { command: "cleanup [--all] [--id <id>]", description: "Remove prepared agent workspaces.", primary: true }
979
+ ]
980
+ },
932
981
  { name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
933
- { name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
982
+ {
983
+ name: "dist",
984
+ summary: "Build/install packaged Rig CLI.",
985
+ usage: ["rig dist <build|install|doctor|rebuild-agent>"],
986
+ commands: [
987
+ { command: "build [--output-dir <dir>]", description: "Build the distributable Rig CLI.", primary: true },
988
+ { command: "install [--scope <scope>] [--path <path>]", description: "Install the built CLI to a scope/path.", primary: true },
989
+ { command: "doctor", description: "Diagnose the dist toolchain and install state.", primary: true },
990
+ { command: "rebuild-agent", description: "Rebuild the agent runtime image, pruning stale images.", primary: true }
991
+ ]
992
+ },
934
993
  { name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
935
- { name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
994
+ {
995
+ name: "remote",
996
+ summary: "Compatibility remote orchestration controls.",
997
+ usage: ["rig remote <status|tasks|watch|pause|resume|continue|stop|refresh|add-iterations|remove-iterations|endpoint ...>"],
998
+ commands: [
999
+ { command: "status [--remote <alias>]", description: "Show the remote orchestration state.", primary: true },
1000
+ { command: "tasks [--remote <alias>]", description: "List the remote's tracked tasks.", primary: true },
1001
+ { command: "watch [--remote <alias>] [--seconds <n>] [--event <type>]", description: "Stream remote orchestration events.", primary: true },
1002
+ { command: "pause [--remote <alias>]", description: "Pause the running remote orchestration.", primary: true },
1003
+ { command: "resume [--remote <alias>] [--max-workers <n>] [--max-iterations <n>] [--direct-merge]", description: "Resume the remote with optional tuning.", primary: true },
1004
+ { command: "continue [--remote <alias>]", description: "Continue a paused remote orchestration.", primary: true },
1005
+ { command: "stop [--remote <alias>]", description: "Stop the remote orchestration.", primary: true },
1006
+ { command: "refresh [--remote <alias>]", description: "Refresh remote state.", primary: true },
1007
+ { command: "add-iterations [--count <n>] [--remote <alias>]", description: "Grant the remote more iterations.", primary: true },
1008
+ { command: "remove-iterations [--count <n>] [--remote <alias>]", description: "Reduce the remote's iteration budget.", primary: true },
1009
+ { command: "endpoint list", description: "List configured remote endpoints.", primary: true },
1010
+ { command: "endpoint add --alias <alias> --host <host> --port <n> [--token <token>]", description: "Register a remote endpoint.", primary: true },
1011
+ { command: "endpoint remove --alias <alias>", description: "Remove a remote endpoint.", primary: true },
1012
+ { command: "endpoint test [--alias <alias>]", description: "Test connectivity to a remote endpoint.", primary: true },
1013
+ { command: "endpoint doctor", description: "Diagnose remote endpoint configuration.", primary: true }
1014
+ ]
1015
+ },
936
1016
  { name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
937
1017
  { name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
938
1018
  { name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }
@@ -96,18 +96,8 @@ function resolveControlPlaneTaskConfigPath(projectRoot) {
96
96
 
97
97
  // packages/cli/src/commands/_authority-runs.ts
98
98
  var RIG_WORKSPACE_ID = "rig-local-workspace";
99
- function normalizeRuntimeAdapter(value) {
100
- const normalized = value?.trim().toLowerCase();
101
- if (!normalized) {
102
- return "pi";
103
- }
104
- if (normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "gpt-codex") {
105
- return "codex";
106
- }
107
- if (normalized === "pi" || normalized === "rig-pi" || normalized === "@rig/pi") {
108
- return "pi";
109
- }
110
- return "claude-code";
99
+ function normalizeRuntimeAdapter(_value) {
100
+ return "pi";
111
101
  }
112
102
  function readLatestBeadRecord(projectRoot, taskId) {
113
103
  const issuesPath = resolve2(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");