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

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 (206) hide show
  1. package/dist/bin/build-rig-binaries.js +40 -8
  2. package/dist/bin/rig.js +23402 -14577
  3. package/dist/src/app/board.js +217 -41
  4. package/dist/src/app-opentui/adapters/command.d.ts +2 -0
  5. package/dist/src/app-opentui/adapters/command.js +329 -0
  6. package/dist/src/app-opentui/adapters/common.js +2 -2
  7. package/dist/src/app-opentui/adapters/doctor.d.ts +0 -2
  8. package/dist/src/app-opentui/adapters/doctor.js +64 -39
  9. package/dist/src/app-opentui/adapters/family.d.ts +62 -0
  10. package/dist/src/app-opentui/adapters/family.js +14305 -0
  11. package/dist/src/app-opentui/adapters/fleet.d.ts +0 -2
  12. package/dist/src/app-opentui/adapters/fleet.js +90 -60
  13. package/dist/src/app-opentui/adapters/inbox.d.ts +12 -2
  14. package/dist/src/app-opentui/adapters/inbox.js +137 -78
  15. package/dist/src/app-opentui/adapters/init.d.ts +0 -2
  16. package/dist/src/app-opentui/adapters/init.js +85 -47
  17. package/dist/src/app-opentui/adapters/inspect.d.ts +52 -0
  18. package/dist/src/app-opentui/adapters/inspect.js +1024 -0
  19. package/dist/src/app-opentui/adapters/pi-attach.d.ts +15 -6
  20. package/dist/src/app-opentui/adapters/pi-attach.js +442 -125
  21. package/dist/src/app-opentui/adapters/pi.d.ts +23 -0
  22. package/dist/src/app-opentui/adapters/pi.js +363 -0
  23. package/dist/src/app-opentui/adapters/plugin.d.ts +84 -0
  24. package/dist/src/app-opentui/adapters/plugin.js +544 -0
  25. package/dist/src/app-opentui/adapters/repo.d.ts +37 -0
  26. package/dist/src/app-opentui/adapters/repo.js +186 -0
  27. package/dist/src/app-opentui/adapters/run-detail.d.ts +9 -2
  28. package/dist/src/app-opentui/adapters/run-detail.js +180 -63
  29. package/dist/src/app-opentui/adapters/server.d.ts +10 -2
  30. package/dist/src/app-opentui/adapters/server.js +191 -45
  31. package/dist/src/app-opentui/adapters/tasks.d.ts +11 -2
  32. package/dist/src/app-opentui/adapters/tasks.js +1123 -143
  33. package/dist/src/app-opentui/adapters/workspace.d.ts +49 -0
  34. package/dist/src/app-opentui/adapters/workspace.js +333 -0
  35. package/dist/src/app-opentui/autocomplete.d.ts +20 -0
  36. package/dist/src/app-opentui/autocomplete.js +576 -0
  37. package/dist/src/app-opentui/bootstrap.d.ts +1 -6
  38. package/dist/src/app-opentui/bootstrap.js +25252 -16474
  39. package/dist/src/app-opentui/command-palette.d.ts +3 -0
  40. package/dist/src/app-opentui/command-palette.js +1010 -0
  41. package/dist/src/app-opentui/command-pty-host.d.ts +62 -0
  42. package/dist/src/app-opentui/command-pty-host.js +248 -0
  43. package/dist/src/app-opentui/drone.js +8 -6
  44. package/dist/src/app-opentui/events.js +1 -1
  45. package/dist/src/app-opentui/fleet-stats.d.ts +32 -0
  46. package/dist/src/app-opentui/fleet-stats.js +114 -0
  47. package/dist/src/app-opentui/focus-manager.d.ts +14 -0
  48. package/dist/src/app-opentui/focus-manager.js +24 -0
  49. package/dist/src/app-opentui/index.js +5431 -2797
  50. package/dist/src/app-opentui/intent.js +179 -50
  51. package/dist/src/app-opentui/keymap.d.ts +21 -0
  52. package/dist/src/app-opentui/keymap.js +1748 -0
  53. package/dist/src/app-opentui/launch-routing.d.ts +16 -0
  54. package/dist/src/app-opentui/launch-routing.js +55 -0
  55. package/dist/src/app-opentui/layout.d.ts +7 -0
  56. package/dist/src/app-opentui/layout.js +13 -6
  57. package/dist/src/app-opentui/list-search.d.ts +24 -0
  58. package/dist/src/app-opentui/list-search.js +88 -1
  59. package/dist/src/app-opentui/pi-host-child.js +99 -17
  60. package/dist/src/app-opentui/pi-pty-host.d.ts +14 -0
  61. package/dist/src/app-opentui/pi-pty-host.js +30 -14
  62. package/dist/src/app-opentui/react/App.d.ts +9 -0
  63. package/dist/src/app-opentui/react/App.js +5144 -0
  64. package/dist/src/app-opentui/react/Backdrop.d.ts +5 -0
  65. package/dist/src/app-opentui/react/Backdrop.js +1834 -0
  66. package/dist/src/app-opentui/react/ChromeHost.d.ts +5 -0
  67. package/dist/src/app-opentui/react/ChromeHost.js +2942 -0
  68. package/dist/src/app-opentui/react/SceneFrameView.d.ts +7 -0
  69. package/dist/src/app-opentui/react/SceneFrameView.js +529 -0
  70. package/dist/src/app-opentui/react/context.d.ts +17 -0
  71. package/dist/src/app-opentui/react/context.js +37 -0
  72. package/dist/src/app-opentui/react/launch.d.ts +2 -0
  73. package/dist/src/app-opentui/react/launch.js +5743 -0
  74. package/dist/src/app-opentui/react/nav.d.ts +18 -0
  75. package/dist/src/app-opentui/react/nav.js +54 -0
  76. package/dist/src/app-opentui/react/scroll.d.ts +12 -0
  77. package/dist/src/app-opentui/react/scroll.js +21 -0
  78. package/dist/src/app-opentui/react/syntax.d.ts +2 -0
  79. package/dist/src/app-opentui/react/syntax.js +64 -0
  80. package/dist/src/app-opentui/registry.js +20428 -4828
  81. package/dist/src/app-opentui/render/ascii-fleet.d.ts +15 -0
  82. package/dist/src/app-opentui/render/ascii-fleet.js +82 -0
  83. package/dist/src/app-opentui/render/constants.d.ts +31 -0
  84. package/dist/src/app-opentui/render/constants.js +66 -0
  85. package/dist/src/app-opentui/render/graphics.d.ts +2 -1
  86. package/dist/src/app-opentui/render/graphics.js +228 -46
  87. package/dist/src/app-opentui/render/image-visual-layer-worker.js +469 -930
  88. package/dist/src/app-opentui/render/image-visual-layer.d.ts +25 -10
  89. package/dist/src/app-opentui/render/image-visual-layer.js +448 -329
  90. package/dist/src/app-opentui/render/native-host.d.ts +37 -0
  91. package/dist/src/app-opentui/render/native-host.js +179 -0
  92. package/dist/src/app-opentui/render/panel-layout.d.ts +38 -0
  93. package/dist/src/app-opentui/render/panel-layout.js +48 -0
  94. package/dist/src/app-opentui/render/panels.d.ts +2 -0
  95. package/dist/src/app-opentui/render/panels.js +78 -38
  96. package/dist/src/app-opentui/render/preloader.d.ts +10 -0
  97. package/dist/src/app-opentui/render/preloader.js +165 -0
  98. package/dist/src/app-opentui/render/scene.d.ts +53 -1
  99. package/dist/src/app-opentui/render/scene.js +195 -6
  100. package/dist/src/app-opentui/render/text.d.ts +7 -1
  101. package/dist/src/app-opentui/render/text.js +15 -8
  102. package/dist/src/app-opentui/render/type-bar.d.ts +2 -1
  103. package/dist/src/app-opentui/render/type-bar.js +113 -39
  104. package/dist/src/app-opentui/runtime-resources.d.ts +16 -0
  105. package/dist/src/app-opentui/runtime-resources.js +62 -0
  106. package/dist/src/app-opentui/runtime.d.ts +44 -1
  107. package/dist/src/app-opentui/runtime.js +5415 -2738
  108. package/dist/src/app-opentui/scenes/command.d.ts +3 -0
  109. package/dist/src/app-opentui/scenes/command.js +117 -0
  110. package/dist/src/app-opentui/scenes/doctor.d.ts +2 -1
  111. package/dist/src/app-opentui/scenes/doctor.js +221 -17
  112. package/dist/src/app-opentui/scenes/error.js +60 -20
  113. package/dist/src/app-opentui/scenes/family-domains/agent.d.ts +2 -0
  114. package/dist/src/app-opentui/scenes/family-domains/agent.js +348 -0
  115. package/dist/src/app-opentui/scenes/family-domains/browser.d.ts +2 -0
  116. package/dist/src/app-opentui/scenes/family-domains/browser.js +195 -0
  117. package/dist/src/app-opentui/scenes/family-domains/dist.d.ts +2 -0
  118. package/dist/src/app-opentui/scenes/family-domains/dist.js +243 -0
  119. package/dist/src/app-opentui/scenes/family-domains/git.d.ts +2 -0
  120. package/dist/src/app-opentui/scenes/family-domains/git.js +195 -0
  121. package/dist/src/app-opentui/scenes/family-domains/github.d.ts +2 -0
  122. package/dist/src/app-opentui/scenes/family-domains/github.js +274 -0
  123. package/dist/src/app-opentui/scenes/family-domains/harness.d.ts +2 -0
  124. package/dist/src/app-opentui/scenes/family-domains/harness.js +152 -0
  125. package/dist/src/app-opentui/scenes/family-domains/index.d.ts +4 -0
  126. package/dist/src/app-opentui/scenes/family-domains/index.js +1679 -0
  127. package/dist/src/app-opentui/scenes/family-domains/kit.d.ts +76 -0
  128. package/dist/src/app-opentui/scenes/family-domains/kit.js +305 -0
  129. package/dist/src/app-opentui/scenes/family-domains/profile.d.ts +2 -0
  130. package/dist/src/app-opentui/scenes/family-domains/profile.js +212 -0
  131. package/dist/src/app-opentui/scenes/family-domains/queue.d.ts +2 -0
  132. package/dist/src/app-opentui/scenes/family-domains/queue.js +146 -0
  133. package/dist/src/app-opentui/scenes/family-domains/remote.d.ts +2 -0
  134. package/dist/src/app-opentui/scenes/family-domains/remote.js +518 -0
  135. package/dist/src/app-opentui/scenes/family-domains/review.d.ts +2 -0
  136. package/dist/src/app-opentui/scenes/family-domains/review.js +280 -0
  137. package/dist/src/app-opentui/scenes/family-domains/setup.d.ts +2 -0
  138. package/dist/src/app-opentui/scenes/family-domains/setup.js +267 -0
  139. package/dist/src/app-opentui/scenes/family-domains/stats.d.ts +2 -0
  140. package/dist/src/app-opentui/scenes/family-domains/stats.js +370 -0
  141. package/dist/src/app-opentui/scenes/family.d.ts +3 -0
  142. package/dist/src/app-opentui/scenes/family.js +2144 -0
  143. package/dist/src/app-opentui/scenes/fleet.js +552 -43
  144. package/dist/src/app-opentui/scenes/handoff.js +342 -35
  145. package/dist/src/app-opentui/scenes/help.js +640 -56
  146. package/dist/src/app-opentui/scenes/inbox.d.ts +2 -1
  147. package/dist/src/app-opentui/scenes/inbox.js +329 -21
  148. package/dist/src/app-opentui/scenes/init.d.ts +2 -1
  149. package/dist/src/app-opentui/scenes/init.js +120 -34
  150. package/dist/src/app-opentui/scenes/inspect.d.ts +3 -0
  151. package/dist/src/app-opentui/scenes/inspect.js +793 -0
  152. package/dist/src/app-opentui/scenes/main.d.ts +2 -1
  153. package/dist/src/app-opentui/scenes/main.js +264 -29
  154. package/dist/src/app-opentui/scenes/pi.d.ts +3 -0
  155. package/dist/src/app-opentui/scenes/pi.js +508 -0
  156. package/dist/src/app-opentui/scenes/plugin.d.ts +3 -0
  157. package/dist/src/app-opentui/scenes/plugin.js +486 -0
  158. package/dist/src/app-opentui/scenes/repo.d.ts +3 -0
  159. package/dist/src/app-opentui/scenes/repo.js +424 -0
  160. package/dist/src/app-opentui/scenes/run-detail.d.ts +2 -1
  161. package/dist/src/app-opentui/scenes/run-detail.js +362 -35
  162. package/dist/src/app-opentui/scenes/server.d.ts +2 -1
  163. package/dist/src/app-opentui/scenes/server.js +243 -26
  164. package/dist/src/app-opentui/scenes/tasks.js +518 -41
  165. package/dist/src/app-opentui/scenes/workspace.d.ts +3 -0
  166. package/dist/src/app-opentui/scenes/workspace.js +426 -0
  167. package/dist/src/app-opentui/selectable.d.ts +19 -0
  168. package/dist/src/app-opentui/selectable.js +79 -0
  169. package/dist/src/app-opentui/state.js +129 -36
  170. package/dist/src/app-opentui/surface-catalog.d.ts +20 -0
  171. package/dist/src/app-opentui/surface-catalog.js +540 -0
  172. package/dist/src/app-opentui/terminal-capabilities.d.ts +7 -0
  173. package/dist/src/app-opentui/terminal-capabilities.js +15 -0
  174. package/dist/src/app-opentui/theme.d.ts +28 -6
  175. package/dist/src/app-opentui/theme.js +61 -8
  176. package/dist/src/app-opentui/types.d.ts +130 -5
  177. package/dist/src/commands/_authority-runs.d.ts +1 -1
  178. package/dist/src/commands/_authority-runs.js +2 -12
  179. package/dist/src/commands/_doctor-checks.js +62 -13
  180. package/dist/src/commands/_help-catalog.js +95 -15
  181. package/dist/src/commands/_operator-view.js +97 -15
  182. package/dist/src/commands/_pi-frontend.d.ts +2 -0
  183. package/dist/src/commands/_pi-frontend.js +97 -13
  184. package/dist/src/commands/_preflight.js +64 -14
  185. package/dist/src/commands/_server-client.js +82 -18
  186. package/dist/src/commands/_server-events.d.ts +26 -0
  187. package/dist/src/commands/_server-events.js +310 -0
  188. package/dist/src/commands/_snapshot-upload.js +62 -13
  189. package/dist/src/commands/agent.js +2 -12
  190. package/dist/src/commands/connect.js +7 -1
  191. package/dist/src/commands/doctor.js +62 -13
  192. package/dist/src/commands/github.js +144 -23
  193. package/dist/src/commands/inbox.js +62 -13
  194. package/dist/src/commands/init.js +82 -18
  195. package/dist/src/commands/inspect.js +62 -13
  196. package/dist/src/commands/run.js +100 -15
  197. package/dist/src/commands/server.js +71 -26
  198. package/dist/src/commands/setup.js +62 -13
  199. package/dist/src/commands/stats.js +157 -28
  200. package/dist/src/commands/task-run-driver.js +64 -25
  201. package/dist/src/commands/task.js +196 -43
  202. package/dist/src/commands.js +419 -123
  203. package/dist/src/index.js +426 -130
  204. package/package.json +11 -10
  205. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.d.ts +0 -2
  206. package/dist/src/app-opentui/render/image-visual-layer-native-canvas.js +0 -1484
@@ -11,19 +11,25 @@ var RIG_UI = {
11
11
  bg: "#070809",
12
12
  bg2: "#0b0c0e",
13
13
  panel: "#101115",
14
- panel2: "#101115",
15
- glass: "#14161b",
16
- ink: "#f2f3f6",
17
- ink2: "#aeb0ba",
18
- ink3: "#6c6e79",
19
- ink4: "#44464f",
14
+ panel2: "#14161b",
15
+ glass: "#1e2230",
16
+ border: "#2a2e3a",
17
+ ink: "#f4f5f8",
18
+ ink2: "#c7c9d3",
19
+ ink3: "#9aa0ae",
20
+ ink4: "#787b86",
20
21
  lime: "#ccff4d",
21
22
  limeDim: "#a9d63f",
22
23
  cyan: "#56d8ff",
24
+ cyanDim: "#3f9fbd",
23
25
  red: "#ff5d5d",
24
26
  yellow: "#ffd24d",
25
27
  magenta: "#ff79b0"
26
28
  };
29
+ var SELECTION_MARKER = "\u258C";
30
+ var SELECTION_MARKER_IDLE = " ";
31
+ var LABEL_WIDTH = 14;
32
+ var COLUMN_GUTTER = " ";
27
33
  var RIG_SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
28
34
  var styles = {
29
35
  ink: otuiFg(RIG_UI.ink),
@@ -39,11 +45,11 @@ var styles = {
39
45
  };
40
46
  function statusColor(status) {
41
47
  switch (status) {
42
- case "running":
43
48
  case "success":
44
49
  case "completed":
45
50
  case "merged":
46
51
  return RIG_UI.lime;
52
+ case "running":
47
53
  case "preparing":
48
54
  case "created":
49
55
  case "validating":
@@ -63,6 +69,46 @@ function statusColor(status) {
63
69
  return RIG_UI.ink3;
64
70
  }
65
71
  }
72
+ function statusGlyph(status) {
73
+ switch (status) {
74
+ case "success":
75
+ case "completed":
76
+ case "merged":
77
+ return "\u2713";
78
+ case "running":
79
+ return "\u25CF";
80
+ case "preparing":
81
+ case "created":
82
+ case "validating":
83
+ case "reviewing":
84
+ case "closing-out":
85
+ case "stopping":
86
+ case "loading":
87
+ case "action":
88
+ return "\u25D0";
89
+ case "needs-attention":
90
+ case "needs_attention":
91
+ return "\u26A0";
92
+ case "failed":
93
+ case "error":
94
+ return "\u2717";
95
+ default:
96
+ return "\xB7";
97
+ }
98
+ }
99
+ function noColorActive() {
100
+ const noColor = process.env.NO_COLOR;
101
+ if (noColor !== undefined && noColor !== "") {
102
+ return true;
103
+ }
104
+ return process.env.RIG_NO_COLOR !== undefined;
105
+ }
106
+ function statusLabel(status) {
107
+ return {
108
+ glyph: statusGlyph(status),
109
+ color: noColorActive() ? RIG_UI.ink : statusColor(status)
110
+ };
111
+ }
66
112
  function sceneTitle(title) {
67
113
  return t`${otuiBold(styles.ink(title))}`;
68
114
  }
@@ -75,14 +121,21 @@ function faint(text) {
75
121
  export {
76
122
  t,
77
123
  styles,
124
+ statusLabel,
125
+ statusGlyph,
78
126
  statusColor,
79
127
  sceneTitle,
128
+ noColorActive,
80
129
  otuiFg as fg,
81
130
  faint,
82
131
  otuiDim as dim,
83
132
  commandText,
84
133
  otuiBold as bold,
85
134
  TextAttributes,
135
+ SELECTION_MARKER_IDLE,
136
+ SELECTION_MARKER,
86
137
  RIG_UI,
87
- RIG_SPINNER_FRAMES
138
+ RIG_SPINNER_FRAMES,
139
+ LABEL_WIDTH,
140
+ COLUMN_GUTTER
88
141
  };
@@ -1,8 +1,8 @@
1
1
  import type { StyledText } from "@opentui/core";
2
2
  import type { RunnerContext } from "../runner";
3
3
  import type { StageLayout } from "./layout";
4
- export type AppSceneId = "main" | "fleet" | "tasks" | "inbox" | "server" | "init" | "doctor" | "run-detail" | "handoff" | "help" | "error";
5
- export type AppActionKind = "none" | "refresh" | "navigate" | "task-run-next" | "task-run-id" | "run-stop" | "run-attach" | "run-steer" | "inbox-approve" | "inbox-reject" | "inbox-answer" | "init-start" | "doctor-run";
4
+ export type AppSceneId = "main" | "fleet" | "tasks" | "inbox" | "server" | "init" | "doctor" | "command" | "run-detail" | "handoff" | "pi" | "plugin" | "repo" | "workspace" | "inspect" | "family" | "help" | "error";
5
+ export type AppActionKind = "none" | "refresh" | "navigate" | "task-run-next" | "task-run-id" | "run-stop" | "run-attach" | "run-steer" | "inbox-approve" | "inbox-reject" | "inbox-answer" | "init-start" | "command-run" | "doctor-run";
6
6
  export type AppIntent = {
7
7
  readonly scene: AppSceneId;
8
8
  readonly argv: readonly string[];
@@ -22,10 +22,37 @@ export type AppFooterState = {
22
22
  readonly message?: string;
23
23
  readonly [key: string]: string | undefined;
24
24
  };
25
+ /** Modal input model for the bottom command bar. nav = vim navigation
26
+ * (printable keys are shortcuts); search = live-filter the current list scene;
27
+ * command = type a full `rig …` command; prompt = capture one value for a
28
+ * pending inline action (inbox answer, run steer) without dropping to a PTY. */
29
+ export type AppTypeBarMode = "nav" | "search" | "command" | "prompt";
30
+ /** Describes an inline prompt: the next submitted value is folded into this
31
+ * intent under `payloadKey`, then dispatched. Keeps answer/steer in-app. */
32
+ export type AppInlinePrompt = {
33
+ readonly label: string;
34
+ readonly scene: AppSceneId;
35
+ readonly argv: readonly string[];
36
+ readonly intentKind: AppActionKind;
37
+ readonly payloadBase: Record<string, unknown>;
38
+ readonly payloadKey: string;
39
+ /** When true, the typed value is tokenized and appended to `argv` (for
40
+ * collecting a parameterized command's args before running it) rather than
41
+ * folded into the action payload. Used by the actionable command catalog (#21). */
42
+ readonly appendValueToArgv?: boolean;
43
+ };
25
44
  export type AppTypeBarState = {
26
45
  readonly value: string;
27
46
  readonly placeholder: string;
28
47
  readonly message?: string;
48
+ readonly mode?: AppTypeBarMode;
49
+ readonly prompt?: AppInlinePrompt;
50
+ };
51
+ /** A pending confirmation gate for a destructive action (#16). The held intent
52
+ * only dispatches on an explicit second Enter; esc cancels. */
53
+ export type AppConfirmState = {
54
+ readonly label: string;
55
+ readonly intent: AppIntent;
29
56
  };
30
57
  export type AppErrorState = {
31
58
  readonly message: string;
@@ -36,6 +63,62 @@ export type AppSelectionState = {
36
63
  readonly index: number;
37
64
  readonly count: number;
38
65
  };
66
+ export type AppSelectableItem = {
67
+ readonly id: string;
68
+ readonly label: string;
69
+ readonly data?: Record<string, unknown>;
70
+ readonly intent?: AppIntent;
71
+ readonly message?: string;
72
+ /** Activating this item opens an inline prompt instead of dispatching an
73
+ * intent — the typed value is folded into the action (#15). */
74
+ readonly prompt?: AppInlinePrompt;
75
+ };
76
+ /** Typed state.data slices (#7). Scalar selections/flags are precisely typed so
77
+ * their reads don't need casts; heterogeneous server-record slices stay `unknown`
78
+ * (consumers narrow them) and the index signature keeps dynamic writes compiling.
79
+ * This retires the untyped `Record<string, unknown>` bag while staying compatible
80
+ * with every existing patch site. */
81
+ export type AppData = {
82
+ readonly selectedRunId?: string;
83
+ readonly selectedTaskId?: string;
84
+ /** When set, the tasks scene shows that task's dedicated DETAIL screen
85
+ * (native-markdown body + actions) instead of the list (#3/#5/#7). */
86
+ readonly taskDetailId?: string;
87
+ readonly selectedInboxRequestId?: string;
88
+ readonly projectConfigured?: boolean;
89
+ readonly lastRefreshError?: string;
90
+ readonly fleet?: unknown;
91
+ readonly tasks?: unknown;
92
+ readonly inbox?: unknown;
93
+ readonly inboxOptimistic?: unknown;
94
+ readonly server?: unknown;
95
+ readonly runDetail?: unknown;
96
+ readonly inspect?: unknown;
97
+ /** Active sub-view of the inspect scene (logs/timeline/diff/failures). */
98
+ readonly inspectView?: string;
99
+ readonly pi?: unknown;
100
+ readonly plugin?: unknown;
101
+ readonly repo?: unknown;
102
+ readonly workspace?: unknown;
103
+ readonly piTerminal?: unknown;
104
+ readonly commandTerminal?: unknown;
105
+ /** Generic family-browser slice: the active family's catalog + live state. */
106
+ readonly family?: unknown;
107
+ /** Which CLI family the family scene is currently showing. */
108
+ readonly familyName?: string;
109
+ /** In-progress command-form state (selected subcommand + adapted field values). */
110
+ readonly familyForm?: unknown;
111
+ /** The drilled-into item id within the active family's bespoke surface — when
112
+ * set, the renderer shows that item's dedicated DETAIL screen (#5). */
113
+ readonly familyDrillId?: string;
114
+ readonly piAttach?: unknown;
115
+ readonly handoff?: unknown;
116
+ readonly doctor?: unknown;
117
+ readonly init?: unknown;
118
+ readonly dispatchingRun?: unknown;
119
+ readonly latestSubmittedRun?: unknown;
120
+ readonly [key: string]: unknown;
121
+ };
39
122
  export type AppState = {
40
123
  readonly projectRoot: string;
41
124
  readonly scene: AppSceneId;
@@ -46,16 +129,22 @@ export type AppState = {
46
129
  readonly typeBar: AppTypeBarState;
47
130
  readonly footer: AppFooterState;
48
131
  readonly selection: AppSelectionState;
49
- readonly data: Record<string, unknown>;
132
+ readonly data: AppData;
50
133
  readonly runtimeReady: boolean;
51
134
  readonly actionLabel?: string;
52
135
  readonly error?: AppErrorState;
136
+ /** Scene back-stack for esc-pops-one-level navigation (#13). */
137
+ readonly history: readonly AppSceneId[];
138
+ /** Pending destructive-action confirmation gate (#16). */
139
+ readonly confirm?: AppConfirmState;
140
+ /** Wall-clock ms of the last successful data refresh, for "updated Ns ago" (#14). */
141
+ readonly dataUpdatedAtMs?: number;
53
142
  };
54
143
  export type AppStatePatch = Omit<Partial<AppState>, "typeBar" | "footer" | "selection" | "data"> & {
55
144
  readonly typeBar?: Partial<AppTypeBarState>;
56
145
  readonly footer?: Partial<AppFooterState>;
57
146
  readonly selection?: Partial<AppSelectionState>;
58
- readonly data?: Record<string, unknown>;
147
+ readonly data?: AppData;
59
148
  };
60
149
  export type AppEvent = {
61
150
  readonly type: "scene.change";
@@ -97,6 +186,11 @@ export type AppEvent = {
97
186
  readonly message: string;
98
187
  readonly hint?: string;
99
188
  readonly cause?: unknown;
189
+ } | {
190
+ readonly type: "confirm.request";
191
+ readonly confirm: AppConfirmState;
192
+ } | {
193
+ readonly type: "confirm.cancel";
100
194
  };
101
195
  export type AppStore = {
102
196
  getState(): AppState;
@@ -112,11 +206,19 @@ export type AppSceneLine = {
112
206
  readonly text: string;
113
207
  readonly styledText?: StyledText;
114
208
  readonly fg?: string;
209
+ readonly bg?: string;
115
210
  readonly bold?: boolean;
116
211
  readonly dim?: boolean;
117
212
  readonly align?: "left" | "center" | "right";
118
- /** Zero-based selectable item index for keyboard/mouse navigation. */
213
+ /** Compacted selectable index into the rendered item list. Derived by the
214
+ * runtime at render time from `selectable`; scenes never set this directly. */
119
215
  readonly selectableIndex?: number;
216
+ /** Stable id of the selectable item this line activates. Derived from
217
+ * `selectable.id` at render time so clicks match by id, not position (#12). */
218
+ readonly selectableId?: string;
219
+ /** The full selectable item this line activates. The runtime DERIVES the
220
+ * scene's selectable list from these (single source of truth, #6/#12). */
221
+ readonly selectable?: AppSelectableItem;
120
222
  /** Activate on single click instead of only selecting/double-clicking. */
121
223
  readonly activateOnClick?: boolean;
122
224
  };
@@ -156,6 +258,27 @@ export type AppSceneFrame = {
156
258
  readonly hideTypeBar?: boolean;
157
259
  /** Raw keypresses should be forwarded to the embedded terminal host. */
158
260
  readonly terminalActive?: boolean;
261
+ /** Render this content with a NATIVE OpenTUI component (Tree-sitter code,
262
+ * diff, or markdown) inside a scrollbox, instead of the AppSceneLine pipeline
263
+ * (#7). The scene's own `lines` still render around it (header/tabs). */
264
+ readonly native?: AppNativeMount;
265
+ };
266
+ /** A scene's request to mount a native OpenTUI renderable in a panel rectangle. */
267
+ export type AppNativeMount = {
268
+ readonly kind: "code" | "diff" | "markdown" | "table";
269
+ /** Source/diff/markdown text for code/diff/markdown kinds. */
270
+ readonly content: string;
271
+ /** Rows for `kind: "table"` — the first row is the header. Rendered with the
272
+ * native TextTableRenderable (read-only dense tables). */
273
+ readonly rows?: readonly (readonly string[])[];
274
+ /** Tree-sitter filetype for `kind: "code"` (e.g. "typescript", "json"). */
275
+ readonly filetype?: string;
276
+ readonly top?: number;
277
+ readonly left?: number;
278
+ readonly width?: number;
279
+ readonly height?: number;
280
+ /** Pin scroll to the bottom (log/diff tails). */
281
+ readonly stickyBottom?: boolean;
159
282
  };
160
283
  export type AppSceneRenderer = (state: AppState, layout?: StageLayout) => AppSceneFrame;
161
284
  export type AppRuntime = {
@@ -164,6 +287,8 @@ export type AppRuntime = {
164
287
  emit(event: AppEvent): void;
165
288
  setScene(scene: AppSceneId, intent?: AppIntent): void;
166
289
  runIntent(intent: AppIntent): Promise<void>;
290
+ /** Pop the scene back-stack one level (esc), refreshing the target (#13). */
291
+ goBack(): Promise<void>;
167
292
  getRunnerContext(): Promise<RunnerContext>;
168
293
  suspend(): void;
169
294
  resume(): void;
@@ -2,7 +2,7 @@ import { type AuthorityRunRecord } from "@rig/runtime/control-plane/authority-fi
2
2
  import type { RunStatus } from "@rig/contracts";
3
3
  export declare const RIG_WORKSPACE_ID = "rig-local-workspace";
4
4
  export type RuntimeAdapter = "claude-code" | "codex" | "pi";
5
- export declare function normalizeRuntimeAdapter(value: string | undefined): RuntimeAdapter;
5
+ export declare function normalizeRuntimeAdapter(_value: string | undefined): RuntimeAdapter;
6
6
  export declare function readLatestBeadRecord(projectRoot: string, taskId: string): Record<string, unknown> | null;
7
7
  export declare function upsertAgentAuthorityRun(projectRoot: string, input: {
8
8
  runId: string;
@@ -16,18 +16,8 @@ function resolveControlPlaneMonorepoRoot(projectRoot) {
16
16
 
17
17
  // packages/cli/src/commands/_authority-runs.ts
18
18
  var RIG_WORKSPACE_ID = "rig-local-workspace";
19
- function normalizeRuntimeAdapter(value) {
20
- const normalized = value?.trim().toLowerCase();
21
- if (!normalized) {
22
- return "pi";
23
- }
24
- if (normalized === "codex" || normalized === "codex-cli" || normalized === "codex-app-server" || normalized === "gpt-codex") {
25
- return "codex";
26
- }
27
- if (normalized === "pi" || normalized === "rig-pi" || normalized === "@rig/pi") {
28
- return "pi";
29
- }
30
- return "claude-code";
19
+ function normalizeRuntimeAdapter(_value) {
20
+ return "pi";
31
21
  }
32
22
  function readLatestBeadRecord(projectRoot, taskId) {
33
23
  const issuesPath = resolve(resolveControlPlaneMonorepoRoot(projectRoot), ".beads", "issues.jsonl");
@@ -134,17 +134,21 @@ function cleanToken(value) {
134
134
  const trimmed = value?.trim();
135
135
  return trimmed ? trimmed : null;
136
136
  }
137
- function readPrivateRemoteSessionToken(projectRoot) {
137
+ function readRemoteAuthState(projectRoot) {
138
138
  const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
139
139
  if (!existsSync2(path))
140
140
  return null;
141
141
  try {
142
142
  const parsed = JSON.parse(readFileSync2(path, "utf8"));
143
- return cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined);
143
+ return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : null;
144
144
  } catch {
145
145
  return null;
146
146
  }
147
147
  }
148
+ function readPrivateRemoteSessionToken(projectRoot) {
149
+ const parsed = readRemoteAuthState(projectRoot);
150
+ return parsed ? cleanToken(typeof parsed.apiSessionToken === "string" ? parsed.apiSessionToken : typeof parsed.sessionToken === "string" ? parsed.sessionToken : undefined) : null;
151
+ }
148
152
  function readGitHubBearerTokenForRemote(projectRoot) {
149
153
  const scopedKey = resolve2(projectRoot);
150
154
  if (scopedGitHubBearerTokens.has(scopedKey))
@@ -155,15 +159,25 @@ function readGitHubBearerTokenForRemote(projectRoot) {
155
159
  return cleanToken(process.env.RIG_SERVER_AUTH_TOKEN) ?? cleanToken(process.env.RIG_REMOTE_AUTH_TOKEN);
156
160
  }
157
161
  function readStoredGitHubAuthToken(projectRoot) {
158
- const path = resolve2(projectRoot, ".rig", "state", "github-auth.json");
159
- if (!existsSync2(path))
162
+ const parsed = readRemoteAuthState(projectRoot);
163
+ return parsed ? cleanToken(typeof parsed.token === "string" ? parsed.token : undefined) : null;
164
+ }
165
+ function inferRemoteServerProjectRootFromAuthState(projectRoot) {
166
+ const repo = readRepoConnection(projectRoot);
167
+ const slug = repo?.project?.trim();
168
+ if (!slug || !/^[^/]+\/[^/]+$/.test(slug))
160
169
  return null;
161
- try {
162
- const parsed = JSON.parse(readFileSync2(path, "utf8"));
163
- return cleanToken(typeof parsed.token === "string" ? parsed.token : undefined);
164
- } catch {
170
+ const auth = readRemoteAuthState(projectRoot);
171
+ const authUpdatedAt = typeof auth?.updatedAt === "string" ? Date.parse(auth.updatedAt) : Number.NaN;
172
+ const repoLinkedAt = typeof repo?.linkedAt === "string" ? Date.parse(repo.linkedAt) : Number.NaN;
173
+ if (Number.isFinite(authUpdatedAt) && Number.isFinite(repoLinkedAt) && authUpdatedAt + 1000 < repoLinkedAt)
165
174
  return null;
166
- }
175
+ const checkoutBaseDir = typeof auth?.checkoutBaseDir === "string" && auth.checkoutBaseDir.trim() ? auth.checkoutBaseDir.trim() : null;
176
+ if (!checkoutBaseDir)
177
+ return null;
178
+ const inferred = `${checkoutBaseDir.replace(/\/+$/, "")}/${slug}`;
179
+ writeRepoServerProjectRoot(projectRoot, inferred);
180
+ return inferred;
167
181
  }
168
182
  function readLocalConnectionFallbackToken(projectRoot) {
169
183
  return readGitHubBearerTokenForRemote(projectRoot) ?? cleanToken(process.env.RIG_GITHUB_TOKEN) ?? readStoredGitHubAuthToken(projectRoot);
@@ -174,7 +188,7 @@ async function ensureServerForCli(projectRoot) {
174
188
  if (selected?.connection.kind === "remote") {
175
189
  reportServerPhase(`Connecting to ${selected.alias}\u2026`);
176
190
  const authToken = readGitHubBearerTokenForRemote(projectRoot);
177
- const serverProjectRoot = selected.serverProjectRoot ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
191
+ const serverProjectRoot = selected.serverProjectRoot ?? inferRemoteServerProjectRootFromAuthState(projectRoot) ?? await backfillRemoteServerProjectRoot(projectRoot, selected.connection.baseUrl, authToken);
178
192
  return {
179
193
  baseUrl: selected.connection.baseUrl,
180
194
  authToken,
@@ -203,7 +217,10 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
203
217
  if (!slug)
204
218
  return null;
205
219
  try {
206
- const response = await fetch(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`, {
220
+ const url = new URL(`${baseUrl}/api/projects/${encodeURIComponent(slug)}`);
221
+ if (authToken && queryAuthFallbackEnabled())
222
+ url.searchParams.set("rt", authToken);
223
+ const response = await fetch(url, {
207
224
  headers: mergeHeaders(undefined, authToken)
208
225
  });
209
226
  if (!response.ok)
@@ -220,10 +237,23 @@ async function backfillRemoteServerProjectRoot(projectRoot, baseUrl, authToken)
220
237
  return null;
221
238
  }
222
239
  }
240
+ function mergeCookie(existing, name, value) {
241
+ const encoded = `${name}=${encodeURIComponent(value)}`;
242
+ if (!existing?.trim())
243
+ return encoded;
244
+ const parts = existing.split(";").map((part) => part.trim()).filter((part) => part && !part.startsWith(`${name}=`));
245
+ return [...parts, encoded].join("; ");
246
+ }
247
+ function queryAuthFallbackEnabled(env = process.env) {
248
+ return env.RIG_ENABLE_QUERY_AUTH_FALLBACK === "1" || env.RIG_QUERY_AUTH_FALLBACK === "1";
249
+ }
223
250
  function mergeHeaders(headers, authToken) {
224
251
  const merged = new Headers(headers);
225
252
  if (authToken) {
226
- merged.set("authorization", `Bearer ${authToken}`);
253
+ const bearer = `Bearer ${authToken}`;
254
+ merged.set("authorization", bearer);
255
+ merged.set("x-auth", bearer);
256
+ merged.set("cookie", mergeCookie(merged.get("cookie"), "rig_auth", authToken));
227
257
  }
228
258
  return merged;
229
259
  }
@@ -284,15 +314,34 @@ async function buildServerFailureContext(projectRoot, server) {
284
314
  hint: "Check the selected server with `rig server status`, or switch with `rig server use <alias|local>`."
285
315
  };
286
316
  }
317
+ function isLoopbackRemoteBaseUrl(baseUrl) {
318
+ try {
319
+ const host = new URL(baseUrl).hostname.toLowerCase();
320
+ return host === "localhost" || host === "127.0.0.1" || host === "::1" || host === "[::1]";
321
+ } catch {
322
+ return false;
323
+ }
324
+ }
325
+ function canUseRemoteWithoutProjectRoot(pathname) {
326
+ 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/");
327
+ }
287
328
  async function requestServerJson(context, pathname, init = {}) {
288
329
  const server = await ensureServerForCli(context.projectRoot);
330
+ const requestUrl = new URL(`${server.baseUrl}${pathname}`);
331
+ if (server.connectionKind === "remote" && !server.serverProjectRoot && !canUseRemoteWithoutProjectRoot(requestUrl.pathname) && (server.authToken || !isLoopbackRemoteBaseUrl(server.baseUrl))) {
332
+ const repo = readRepoConnection(context.projectRoot);
333
+ throw new CliError(`Remote server is selected for ${repo?.project ?? "this repo"}, but this checkout has no server-host project root link.`, 1, { hint: "Run `rig init --repair` or `rig init --yes --repo owner/repo --server remote` to repair the remote project link before task/run commands." });
334
+ }
289
335
  const headers = mergeHeaders(init.headers, server.authToken);
290
336
  if (server.serverProjectRoot)
291
337
  headers.set("x-rig-project-root", server.serverProjectRoot);
338
+ if (server.connectionKind === "remote" && server.authToken && queryAuthFallbackEnabled()) {
339
+ requestUrl.searchParams.set("rt", server.authToken);
340
+ }
292
341
  reportServerPhase(`${(init.method ?? "GET").toUpperCase()} ${pathname.split("?")[0]}\u2026`);
293
342
  let response;
294
343
  try {
295
- response = await fetch(`${server.baseUrl}${pathname}`, {
344
+ response = await fetch(requestUrl, {
296
345
  ...init,
297
346
  headers
298
347
  });
@@ -254,30 +254,62 @@ var PRIMARY_GROUPS = [
254
254
  }
255
255
  ];
256
256
  var ADVANCED_GROUPS = [
257
- { name: "setup", summary: "Bootstrap/check local setup.", usage: ["rig setup <bootstrap|check|preflight>"], commands: [{ command: "bootstrap|check|preflight", description: "Setup helpers." }] },
258
- { name: "profile", summary: "Runtime profile/model defaults.", usage: ["rig profile <show|set>"], commands: [{ command: "show", description: "Show active profile." }] },
257
+ {
258
+ name: "setup",
259
+ summary: "Bootstrap/check local setup.",
260
+ usage: ["rig setup <bootstrap|check|preflight>"],
261
+ commands: [
262
+ { command: "bootstrap", description: "Bootstrap local setup dependencies.", primary: true },
263
+ { command: "check", description: "Check local setup state (toolchain, deps, config).", primary: true },
264
+ { command: "preflight", description: "Run preflight checks before a run.", primary: true }
265
+ ]
266
+ },
267
+ {
268
+ name: "profile",
269
+ summary: "Runtime profile/model defaults.",
270
+ usage: ["rig profile <show|set>"],
271
+ commands: [
272
+ { command: "show", description: "Show the active execution profile.", primary: true },
273
+ { command: "set [--model <model>] [--runtime <runtime>] [--plugin <plugin>]", description: "Set model/runtime/plugin profile defaults.", primary: true }
274
+ ]
275
+ },
259
276
  {
260
277
  name: "review",
261
278
  summary: "Inspect or change completion review gate policy.",
262
279
  usage: ["rig review <show|set>"],
263
280
  commands: [
264
281
  { command: "show", description: "Show current review gate settings." },
265
- { command: "set <off|advisory|required> [--provider greptile]", description: "Change review strictness/provider." }
282
+ { command: "set <off|advisory|required> [--provider <provider>]", description: "Change review strictness/provider (e.g. --provider greptile)." }
266
283
  ],
267
284
  examples: ["rig review show", "rig review set required --provider greptile"],
268
285
  next: ["Use `rig inbox approvals` for blocked run handoffs."]
269
286
  },
270
287
  {
271
288
  name: "browser",
272
- summary: "Browser/app diagnostics for browser-required tasks.",
273
- usage: ["rig browser <help|explain|demo|app|hp-next> [options]"],
289
+ summary: "Browser workstation actions for browser-required tasks: launch, check, CDP probe, profile reset, and app-specific smokes.",
290
+ usage: ["rig browser <help|explain|demo|hp-next|cdp-probe|profile-persistence|profile-lock-check|smoke-test> [options]"],
274
291
  commands: [
275
- { command: "help", description: "Rich browser command help (canonical: `rig browser help`)." },
276
- { command: "explain", description: "Explain the browser-required task contract." },
277
- { command: "demo", description: "Run browser demo flows against a local page." },
278
- { command: "app", description: "Launch the Rig Browser workstation app." },
279
- { command: "hp-next <dev|check|e2e|reset>", description: "Drive the hp-next browser test harness." }
280
- ]
292
+ { command: "help", description: "Rich browser command help (canonical: `rig browser help`).", primary: true },
293
+ { command: "explain", description: "Explain the browser-required task contract and runtime helper commands.", primary: true },
294
+ { 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 },
295
+ { command: "hp-next dev", description: "Start hp-next Rig Browser in dev/watch mode.", primary: true },
296
+ { command: "hp-next start", description: "Build/start the hp-next browser workstation without watch mode.", primary: true },
297
+ { command: "hp-next check", description: "Validate the hp-next CDP endpoint on the configured port.", primary: true },
298
+ { command: "hp-next e2e", description: "Run hp-next browser e2e smoke checks through Rig Browser.", primary: true },
299
+ { command: "hp-next reset", description: "Reset the hp-next browser profile when stale browser state is suspected.", primary: true },
300
+ { command: "cdp-probe", description: "Run an isolated CDP attach/evaluate/layout probe." },
301
+ { command: "profile-persistence", description: "Verify a named browser profile persists browser state." },
302
+ { command: "profile-lock-check", description: "Verify concurrent launches reject the same profile." },
303
+ { command: "smoke-test", description: "Run the browser package smoke test." }
304
+ ],
305
+ examples: [
306
+ "rig browser help",
307
+ "rig browser hp-next check",
308
+ "rig browser hp-next e2e",
309
+ "rig browser cdp-probe",
310
+ "rig browser profile-lock-check"
311
+ ],
312
+ next: ["Inside a task run, use rig-browser-launch, rig-browser-check, and rig-browser-attach-info from the worker PATH."]
281
313
  },
282
314
  {
283
315
  name: "pi",
@@ -292,12 +324,60 @@ var ADVANCED_GROUPS = [
292
324
  examples: ["rig pi search subagents", "rig pi add pi-subagents", "rig pi list"],
293
325
  next: ["Config-managed extensions: declare `runtime: { pi: { packages: [...] } }` in rig.config.ts \u2014 workers pick them up automatically."]
294
326
  },
295
- { name: "queue", summary: "Run task queues locally.", usage: ["rig queue run [options]"], commands: [{ command: "run", description: "Process queue work." }] },
296
- { name: "agent", summary: "Runtime agent workspace helpers.", usage: ["rig agent <list|prepare|run|cleanup>"], commands: [{ command: "list", description: "List prepared agents." }] },
327
+ {
328
+ name: "queue",
329
+ summary: "Run task queues locally.",
330
+ usage: ["rig queue run [--workers <n>] [--max-tasks <n>] [--action validate|verify|pipeline] [--isolation off|worktree] [--no-runtime-reuse] [--fail-fast] [--skip-project-sync]"],
331
+ commands: [
332
+ { 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 }
333
+ ]
334
+ },
335
+ {
336
+ name: "agent",
337
+ summary: "Runtime agent workspace helpers.",
338
+ usage: ["rig agent <list|prepare|run|cleanup>"],
339
+ commands: [
340
+ { command: "list", description: "List prepared agent runtimes.", primary: true },
341
+ { command: "prepare [--id <id>] [--mode <mode>] [--task <task>]", description: "Prepare an isolated agent runtime workspace.", primary: true },
342
+ { command: "run [--id <id>] [--mode <mode>] [--task <task>] [--skip-project-sync]", description: "Prepare (if needed) and run an agent in its workspace.", primary: true },
343
+ { command: "cleanup [--all] [--id <id>]", description: "Remove prepared agent workspaces.", primary: true }
344
+ ]
345
+ },
297
346
  { name: "inspector", summary: "Event stream and drift scanners.", usage: ["rig inspector <stream|scan-upstream-drift>"], commands: [{ command: "stream", description: "Stream events." }] },
298
- { name: "dist", summary: "Build/install packaged Rig CLI.", usage: ["rig dist <build|install|doctor>"], commands: [{ command: "build", description: "Build distribution." }] },
347
+ {
348
+ name: "dist",
349
+ summary: "Build/install packaged Rig CLI.",
350
+ usage: ["rig dist <build|install|doctor|rebuild-agent>"],
351
+ commands: [
352
+ { command: "build [--output-dir <dir>]", description: "Build the distributable Rig CLI.", primary: true },
353
+ { command: "install [--scope <scope>] [--path <path>]", description: "Install the built CLI to a scope/path.", primary: true },
354
+ { command: "doctor", description: "Diagnose the dist toolchain and install state.", primary: true },
355
+ { command: "rebuild-agent", description: "Rebuild the agent runtime image, pruning stale images.", primary: true }
356
+ ]
357
+ },
299
358
  { name: "workspace", summary: "Workspace topology/service helpers.", usage: ["rig workspace <summary|topology|remote-hosts>"], commands: [{ command: "summary", description: "Show workspace summary." }] },
300
- { name: "remote", summary: "Compatibility remote orchestration controls.", usage: ["rig remote <status|watch|pause|resume|...>"], commands: [{ command: "status", description: "Show remote state." }] },
359
+ {
360
+ name: "remote",
361
+ summary: "Compatibility remote orchestration controls.",
362
+ usage: ["rig remote <status|tasks|watch|pause|resume|continue|stop|refresh|add-iterations|remove-iterations|endpoint ...>"],
363
+ commands: [
364
+ { command: "status [--remote <alias>]", description: "Show the remote orchestration state.", primary: true },
365
+ { command: "tasks [--remote <alias>]", description: "List the remote's tracked tasks.", primary: true },
366
+ { command: "watch [--remote <alias>] [--seconds <n>] [--event <type>]", description: "Stream remote orchestration events.", primary: true },
367
+ { command: "pause [--remote <alias>]", description: "Pause the running remote orchestration.", primary: true },
368
+ { command: "resume [--remote <alias>] [--max-workers <n>] [--max-iterations <n>] [--direct-merge]", description: "Resume the remote with optional tuning.", primary: true },
369
+ { command: "continue [--remote <alias>]", description: "Continue a paused remote orchestration.", primary: true },
370
+ { command: "stop [--remote <alias>]", description: "Stop the remote orchestration.", primary: true },
371
+ { command: "refresh [--remote <alias>]", description: "Refresh remote state.", primary: true },
372
+ { command: "add-iterations [--count <n>] [--remote <alias>]", description: "Grant the remote more iterations.", primary: true },
373
+ { command: "remove-iterations [--count <n>] [--remote <alias>]", description: "Reduce the remote's iteration budget.", primary: true },
374
+ { command: "endpoint list", description: "List configured remote endpoints.", primary: true },
375
+ { command: "endpoint add --alias <alias> --host <host> --port <n> [--token <token>]", description: "Register a remote endpoint.", primary: true },
376
+ { command: "endpoint remove --alias <alias>", description: "Remove a remote endpoint.", primary: true },
377
+ { command: "endpoint test [--alias <alias>]", description: "Test connectivity to a remote endpoint.", primary: true },
378
+ { command: "endpoint doctor", description: "Diagnose remote endpoint configuration.", primary: true }
379
+ ]
380
+ },
301
381
  { name: "git", summary: "Pass through to Rig git-flow helper.", usage: ["rig git <args...>"], commands: [{ command: "<args...>", description: "Advanced git flow operations." }] },
302
382
  { name: "harness", summary: "Pass through to runtime harness CLI.", usage: ["rig harness <args...>"], commands: [{ command: "<args...>", description: "Advanced harness operations." }] },
303
383
  { name: "test", summary: "Project test wrappers.", usage: ["rig test <unit|e2e|all>"], commands: [{ command: "all", description: "Run configured project tests." }] }