@jmoyers/harness 0.1.11 → 0.1.20

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 (232) hide show
  1. package/README.md +31 -39
  2. package/package.json +31 -11
  3. package/packages/harness-ai/src/anthropic-protocol.ts +68 -68
  4. package/packages/harness-ai/src/stream-text.ts +13 -91
  5. package/packages/harness-ui/src/frame-primitives.ts +158 -0
  6. package/packages/harness-ui/src/index.ts +18 -0
  7. package/packages/harness-ui/src/interaction/conversation-input-forwarder.ts +221 -0
  8. package/packages/harness-ui/src/interaction/conversation-selection-input.ts +213 -0
  9. package/packages/harness-ui/src/interaction/global-shortcut-input.ts +172 -0
  10. package/{src/ui → packages/harness-ui/src/interaction}/input-preflight.ts +10 -12
  11. package/{src/ui → packages/harness-ui/src/interaction}/input-token-router.ts +120 -69
  12. package/packages/harness-ui/src/interaction/input.ts +420 -0
  13. package/packages/harness-ui/src/interaction/left-nav-input.ts +166 -0
  14. package/{src/ui → packages/harness-ui/src/interaction}/main-pane-pointer-input.ts +91 -23
  15. package/{src/ui → packages/harness-ui/src/interaction}/pointer-routing-input.ts +112 -48
  16. package/packages/harness-ui/src/interaction/rail-pointer-input.ts +62 -0
  17. package/packages/harness-ui/src/interaction/repository-fold-input.ts +118 -0
  18. package/packages/harness-ui/src/kit.ts +476 -0
  19. package/packages/harness-ui/src/layout.ts +238 -0
  20. package/packages/harness-ui/src/modal-manager.ts +222 -0
  21. package/{src/ui → packages/harness-ui/src}/screen.ts +53 -26
  22. package/packages/harness-ui/src/surface.ts +252 -0
  23. package/packages/harness-ui/src/text-layout.ts +210 -0
  24. package/packages/nim-core/src/contracts.ts +239 -0
  25. package/packages/nim-core/src/event-store.ts +299 -0
  26. package/packages/nim-core/src/events.ts +53 -0
  27. package/packages/nim-core/src/index.ts +9 -0
  28. package/packages/nim-core/src/provider-router.ts +129 -0
  29. package/packages/nim-core/src/providers/anthropic-driver.ts +291 -0
  30. package/packages/nim-core/src/runtime-factory.ts +49 -0
  31. package/packages/nim-core/src/runtime.ts +1797 -0
  32. package/packages/nim-core/src/session-store.ts +516 -0
  33. package/packages/nim-core/src/telemetry.ts +48 -0
  34. package/packages/nim-test-tui/src/index.ts +150 -0
  35. package/packages/nim-ui-core/src/index.ts +1 -0
  36. package/packages/nim-ui-core/src/projection.ts +87 -0
  37. package/scripts/codex-live-mux-runtime.ts +2 -3872
  38. package/scripts/control-plane-daemon.ts +11 -0
  39. package/scripts/harness-bin.js +5 -0
  40. package/scripts/harness-commands.ts +300 -0
  41. package/scripts/harness-runtime.ts +82 -0
  42. package/scripts/harness.ts +33 -3019
  43. package/scripts/nim-tui-smoke.ts +748 -0
  44. package/src/cli/auth/runtime.ts +948 -0
  45. package/src/cli/gateway/runtime.ts +1872 -0
  46. package/src/cli/parsing/flags.ts +23 -0
  47. package/src/cli/parsing/session.ts +42 -0
  48. package/src/cli/runtime/context.ts +193 -0
  49. package/src/cli/runtime-app/application.ts +392 -0
  50. package/src/cli/runtime-infra/gateway-control.ts +729 -0
  51. package/{scripts/harness-inspector.ts → src/cli/workflows/inspector.ts} +14 -11
  52. package/src/cli/workflows/runtime.ts +965 -0
  53. package/src/clients/tui/left-rail-interactions.ts +519 -0
  54. package/src/clients/tui/main-pane-interactions.ts +509 -0
  55. package/src/clients/tui/modal-input-routing.ts +71 -0
  56. package/src/clients/tui/render-snapshot-adapter.ts +88 -0
  57. package/src/clients/web/synced-selectors.ts +132 -0
  58. package/src/codex/live-session.ts +82 -29
  59. package/src/config/config-core.ts +348 -8
  60. package/src/config/harness.config.template.jsonc +33 -0
  61. package/src/control-plane/agent-realtime-api.ts +82 -427
  62. package/src/control-plane/session-summary.ts +10 -81
  63. package/src/control-plane/status/reducer-base.ts +12 -12
  64. package/src/control-plane/status/reducers/claude-status-reducer.ts +3 -3
  65. package/src/control-plane/status/reducers/codex-status-reducer.ts +4 -4
  66. package/src/control-plane/status/reducers/cursor-status-reducer.ts +3 -3
  67. package/src/control-plane/stream-client.ts +12 -2
  68. package/src/control-plane/stream-command-parser.ts +83 -143
  69. package/src/control-plane/stream-protocol.ts +53 -37
  70. package/src/control-plane/stream-server-command.ts +376 -69
  71. package/src/control-plane/stream-server-session-runtime.ts +3 -2
  72. package/src/control-plane/stream-server.ts +864 -70
  73. package/src/control-plane/stream-session-runtime-types.ts +41 -0
  74. package/src/{mux/live-mux/control-plane-records.ts → core/contracts/records.ts} +24 -97
  75. package/src/core/state/observed-stream-cursor.ts +43 -0
  76. package/src/core/state/synced-observed-state.ts +273 -0
  77. package/src/core/store/harness-synced-store.ts +81 -0
  78. package/src/diff/budget.ts +136 -0
  79. package/src/diff/build.ts +289 -0
  80. package/src/diff/chunker.ts +146 -0
  81. package/src/diff/git-invoke.ts +315 -0
  82. package/src/diff/git-parse.ts +472 -0
  83. package/src/diff/hash.ts +70 -0
  84. package/src/diff/index.ts +24 -0
  85. package/src/diff/normalize.ts +134 -0
  86. package/src/diff/types.ts +178 -0
  87. package/src/diff-ui/args.ts +346 -0
  88. package/src/diff-ui/commands.ts +123 -0
  89. package/src/diff-ui/finder.ts +94 -0
  90. package/src/diff-ui/highlight.ts +127 -0
  91. package/src/diff-ui/index.ts +2 -0
  92. package/src/diff-ui/model.ts +141 -0
  93. package/src/diff-ui/pager.ts +412 -0
  94. package/src/diff-ui/render.ts +337 -0
  95. package/src/diff-ui/runtime.ts +379 -0
  96. package/src/diff-ui/state.ts +224 -0
  97. package/src/diff-ui/types.ts +236 -0
  98. package/src/domain/workspace.ts +68 -5
  99. package/src/mux/control-plane-op-queue.ts +93 -7
  100. package/src/mux/conversation-rail.ts +28 -71
  101. package/src/mux/dual-pane-core.ts +13 -13
  102. package/src/mux/harness-core-ui.ts +313 -42
  103. package/src/mux/input-shortcuts.ts +13 -131
  104. package/src/mux/keybinding-catalog.ts +340 -0
  105. package/src/mux/keybinding-registry.ts +103 -0
  106. package/src/mux/live-mux/command-menu-open-in.ts +280 -0
  107. package/src/mux/live-mux/command-menu.ts +167 -4
  108. package/src/mux/live-mux/conversation-state.ts +13 -0
  109. package/src/mux/live-mux/directory-resolution.ts +1 -1
  110. package/src/mux/live-mux/git-snapshot.ts +33 -2
  111. package/src/mux/live-mux/global-shortcut-handlers.ts +6 -0
  112. package/src/mux/live-mux/home-pane-drop.ts +1 -1
  113. package/src/mux/live-mux/home-pane-pointer.ts +10 -0
  114. package/src/mux/live-mux/input-forwarding.ts +59 -2
  115. package/src/mux/live-mux/left-nav-activation.ts +124 -7
  116. package/src/mux/live-mux/left-nav.ts +35 -0
  117. package/src/mux/live-mux/link-click.ts +292 -0
  118. package/src/mux/live-mux/modal-command-menu-handler.ts +46 -9
  119. package/src/mux/live-mux/modal-conversation-handlers.ts +5 -1
  120. package/src/mux/live-mux/modal-input-reducers.ts +77 -12
  121. package/src/mux/live-mux/modal-overlays.ts +168 -34
  122. package/src/mux/live-mux/modal-pointer.ts +3 -7
  123. package/src/mux/live-mux/modal-prompt-handlers.ts +23 -2
  124. package/src/mux/live-mux/modal-release-notes-handler.ts +111 -0
  125. package/src/mux/live-mux/modal-task-editor-handler.ts +16 -11
  126. package/src/mux/live-mux/pointer-routing.ts +5 -2
  127. package/src/mux/live-mux/project-pane-pointer.ts +8 -0
  128. package/src/mux/live-mux/rail-layout.ts +33 -30
  129. package/src/mux/live-mux/release-notes.ts +383 -0
  130. package/src/mux/live-mux/render-trace-analysis.ts +52 -7
  131. package/src/mux/live-mux/repository-folding.ts +3 -0
  132. package/src/mux/live-mux/selection.ts +0 -4
  133. package/src/mux/live-mux/session-diagnostics-paths.ts +21 -0
  134. package/src/mux/project-pane-github-review.ts +271 -0
  135. package/src/mux/render-frame.ts +4 -0
  136. package/src/mux/runtime-app/codex-live-mux-runtime.ts +5191 -0
  137. package/src/mux/task-composer.ts +21 -14
  138. package/src/mux/task-focused-pane.ts +118 -117
  139. package/src/mux/task-screen-keybindings.ts +10 -101
  140. package/src/mux/workspace-rail-model.ts +270 -104
  141. package/src/mux/workspace-rail.ts +45 -22
  142. package/src/pty/session-broker.ts +1 -1
  143. package/{scripts → src/recording}/terminal-recording-gif-lib.ts +2 -2
  144. package/src/services/control-plane.ts +50 -32
  145. package/src/services/conversation-lifecycle.ts +118 -87
  146. package/src/services/conversation-startup-hydration.ts +20 -12
  147. package/src/services/directory-hydration.ts +21 -16
  148. package/src/services/event-persistence.ts +7 -0
  149. package/src/services/left-rail-pointer-handler.ts +329 -0
  150. package/src/services/mux-ui-state-persistence.ts +5 -1
  151. package/src/services/recording.ts +34 -26
  152. package/src/services/runtime-command-menu-agent-tools.ts +1 -1
  153. package/src/services/runtime-control-actions.ts +79 -61
  154. package/src/services/runtime-control-plane-ops.ts +122 -83
  155. package/src/services/runtime-conversation-actions.ts +40 -26
  156. package/src/services/runtime-conversation-activation.ts +73 -46
  157. package/src/services/runtime-conversation-starter.ts +53 -45
  158. package/src/services/runtime-conversation-title-edit.ts +91 -80
  159. package/src/services/runtime-envelope-handler.ts +107 -105
  160. package/src/services/runtime-git-state.ts +42 -29
  161. package/src/services/runtime-layout-resize.ts +3 -1
  162. package/src/services/runtime-left-rail-render.ts +99 -63
  163. package/src/services/runtime-nim-cli-session.ts +438 -0
  164. package/src/services/runtime-nim-session.ts +705 -0
  165. package/src/services/runtime-nim-tool-bridge.ts +141 -0
  166. package/src/services/runtime-observed-event-projection-pipeline.ts +45 -0
  167. package/src/services/runtime-process-wiring.ts +29 -36
  168. package/src/services/runtime-project-pane-github-review-cache.ts +164 -0
  169. package/src/services/runtime-render-flush.ts +63 -70
  170. package/src/services/runtime-render-lifecycle.ts +65 -64
  171. package/src/services/runtime-render-orchestrator.ts +55 -45
  172. package/src/services/runtime-render-pipeline.ts +106 -103
  173. package/src/services/runtime-render-state.ts +62 -49
  174. package/src/services/runtime-repository-actions.ts +97 -72
  175. package/src/services/runtime-right-pane-render.ts +80 -53
  176. package/src/services/runtime-shutdown.ts +38 -35
  177. package/src/services/runtime-stream-subscriptions.ts +35 -27
  178. package/src/services/runtime-task-composer-persistence.ts +71 -59
  179. package/src/services/runtime-task-composer-snapshot.ts +14 -0
  180. package/src/services/runtime-task-editor-actions.ts +46 -29
  181. package/src/services/runtime-task-pane-actions.ts +220 -134
  182. package/src/services/runtime-task-pane-shortcuts.ts +323 -123
  183. package/src/services/runtime-workspace-observed-effect-queue.ts +25 -0
  184. package/src/services/runtime-workspace-observed-events.ts +33 -184
  185. package/src/services/runtime-workspace-observed-transition-policy.ts +228 -0
  186. package/src/services/session-diagnostics-store.ts +217 -0
  187. package/src/services/startup-background-resume.ts +26 -21
  188. package/src/services/startup-orchestrator.ts +16 -13
  189. package/src/services/startup-paint-tracker.ts +29 -21
  190. package/src/services/startup-persisted-conversation-queue.ts +19 -13
  191. package/src/services/startup-settled-gate.ts +25 -15
  192. package/src/services/startup-shutdown.ts +18 -22
  193. package/src/services/startup-state-hydration.ts +44 -34
  194. package/src/services/startup-visibility.ts +12 -4
  195. package/src/services/task-pane-selection-actions.ts +89 -72
  196. package/src/services/task-planning-hydration.ts +24 -18
  197. package/src/services/task-planning-observed-events.ts +50 -52
  198. package/src/services/workspace-observed-events.ts +66 -63
  199. package/src/storage/storage-lifecycle-core.ts +438 -0
  200. package/src/store/control-plane-store-normalize.ts +33 -242
  201. package/src/store/control-plane-store-types.ts +1 -35
  202. package/src/store/control-plane-store.ts +360 -56
  203. package/src/store/event-store.ts +366 -8
  204. package/src/terminal/snapshot-oracle.ts +207 -94
  205. package/src/ui/mux-theme.ts +112 -8
  206. package/src/ui/panes/home-gridfire.ts +40 -31
  207. package/src/ui/panes/home.ts +10 -2
  208. package/src/ui/panes/nim.ts +315 -0
  209. package/src/mux/live-mux/actions-task.ts +0 -115
  210. package/src/mux/live-mux/left-rail-actions.ts +0 -118
  211. package/src/mux/live-mux/left-rail-conversation-click.ts +0 -85
  212. package/src/mux/live-mux/left-rail-pointer.ts +0 -74
  213. package/src/mux/live-mux/task-pane-shortcuts.ts +0 -206
  214. package/src/services/runtime-directory-actions.ts +0 -164
  215. package/src/services/runtime-input-pipeline.ts +0 -50
  216. package/src/services/runtime-input-router.ts +0 -195
  217. package/src/services/runtime-main-pane-input.ts +0 -230
  218. package/src/services/runtime-modal-input.ts +0 -137
  219. package/src/services/runtime-navigation-input.ts +0 -197
  220. package/src/services/runtime-rail-input.ts +0 -279
  221. package/src/services/runtime-task-pane.ts +0 -62
  222. package/src/services/runtime-workspace-actions.ts +0 -158
  223. package/src/ui/conversation-input-forwarder.ts +0 -114
  224. package/src/ui/conversation-selection-input.ts +0 -103
  225. package/src/ui/global-shortcut-input.ts +0 -89
  226. package/src/ui/input.ts +0 -269
  227. package/src/ui/kit.ts +0 -509
  228. package/src/ui/left-nav-input.ts +0 -80
  229. package/src/ui/left-rail-pointer-input.ts +0 -148
  230. package/src/ui/modals/manager.ts +0 -218
  231. package/src/ui/repository-fold-input.ts +0 -91
  232. package/src/ui/surface.ts +0 -224
@@ -0,0 +1,271 @@
1
+ export type ProjectPaneGitHubToggleAction = `project.github.toggle:${string}`;
2
+
3
+ type ProjectPaneGitHubPrLifecycleState = 'draft' | 'open' | 'merged' | 'closed';
4
+ type ProjectPaneGitHubCiRollup =
5
+ | 'pending'
6
+ | 'success'
7
+ | 'failure'
8
+ | 'cancelled'
9
+ | 'neutral'
10
+ | 'none';
11
+
12
+ export interface ProjectPaneGitHubReviewComment {
13
+ readonly commentId: string;
14
+ readonly authorLogin: string | null;
15
+ readonly body: string;
16
+ readonly url: string | null;
17
+ readonly createdAt: string;
18
+ readonly updatedAt: string;
19
+ }
20
+
21
+ export interface ProjectPaneGitHubReviewThread {
22
+ readonly threadId: string;
23
+ readonly isResolved: boolean;
24
+ readonly isOutdated: boolean;
25
+ readonly resolvedByLogin: string | null;
26
+ readonly comments: readonly ProjectPaneGitHubReviewComment[];
27
+ }
28
+
29
+ export interface ProjectPaneGitHubPullRequestSummary {
30
+ readonly number: number;
31
+ readonly title: string;
32
+ readonly url: string;
33
+ readonly authorLogin: string | null;
34
+ readonly headBranch: string;
35
+ readonly baseBranch: string;
36
+ readonly state: ProjectPaneGitHubPrLifecycleState;
37
+ readonly isDraft: boolean;
38
+ readonly mergedAt: string | null;
39
+ readonly closedAt: string | null;
40
+ readonly ciRollup?: ProjectPaneGitHubCiRollup | null;
41
+ readonly updatedAt: string;
42
+ readonly createdAt: string;
43
+ }
44
+
45
+ export interface ProjectPaneGitHubReviewSummary {
46
+ readonly status: 'loading' | 'ready' | 'error';
47
+ readonly branchName: string | null;
48
+ readonly branchSource: 'pinned' | 'current' | null;
49
+ readonly pr: ProjectPaneGitHubPullRequestSummary | null;
50
+ readonly openThreads: readonly ProjectPaneGitHubReviewThread[];
51
+ readonly resolvedThreads: readonly ProjectPaneGitHubReviewThread[];
52
+ readonly errorMessage: string | null;
53
+ }
54
+
55
+ interface BuildProjectPaneGitHubReviewLinesInput {
56
+ readonly review: ProjectPaneGitHubReviewSummary;
57
+ readonly expandedNodeIds: ReadonlySet<string>;
58
+ }
59
+
60
+ interface BuildProjectPaneGitHubReviewLinesResult {
61
+ readonly lines: readonly string[];
62
+ readonly actionByRelativeLineIndex: Readonly<Record<number, ProjectPaneGitHubToggleAction>>;
63
+ }
64
+
65
+ const OPEN_THREAD_GROUP_NODE_ID = 'github/open-threads';
66
+ const RESOLVED_THREAD_GROUP_NODE_ID = 'github/resolved-threads';
67
+
68
+ function sanitizeInlineText(value: string): string {
69
+ const collapsed = value.replace(/\s+/gu, ' ').trim();
70
+ return collapsed;
71
+ }
72
+
73
+ function commentPreview(body: string, maxLength = 160): string {
74
+ const normalized = sanitizeInlineText(body);
75
+ if (normalized.length <= maxLength) {
76
+ return normalized;
77
+ }
78
+ return `${normalized.slice(0, maxLength - 1)}…`;
79
+ }
80
+
81
+ function formatAuthor(login: string | null): string {
82
+ const normalized = login?.trim() ?? '';
83
+ return normalized.length > 0 ? `@${normalized}` : '@unknown';
84
+ }
85
+
86
+ function countComments(threads: readonly ProjectPaneGitHubReviewThread[]): number {
87
+ let total = 0;
88
+ for (const thread of threads) {
89
+ total += thread.comments.length;
90
+ }
91
+ return total;
92
+ }
93
+
94
+ function prStateLabel(pr: ProjectPaneGitHubPullRequestSummary): string {
95
+ if (pr.isDraft || pr.state === 'draft') {
96
+ return 'draft';
97
+ }
98
+ if (pr.state === 'merged') {
99
+ return 'merged';
100
+ }
101
+ if (pr.state === 'closed') {
102
+ return 'closed';
103
+ }
104
+ return 'open';
105
+ }
106
+
107
+ function toggleAction(nodeId: string): ProjectPaneGitHubToggleAction {
108
+ return `project.github.toggle:${nodeId}`;
109
+ }
110
+
111
+ function threadNodeId(thread: ProjectPaneGitHubReviewThread): string {
112
+ return `github/thread:${thread.threadId}`;
113
+ }
114
+
115
+ function pushLine(
116
+ lines: string[],
117
+ actionByRelativeLineIndex: Record<number, ProjectPaneGitHubToggleAction>,
118
+ line: string,
119
+ action: ProjectPaneGitHubToggleAction | null,
120
+ ): void {
121
+ const nextIndex = lines.length;
122
+ lines.push(line);
123
+ if (action !== null) {
124
+ actionByRelativeLineIndex[nextIndex] = action;
125
+ }
126
+ }
127
+
128
+ function appendThreadGroup(
129
+ lines: string[],
130
+ actionByRelativeLineIndex: Record<number, ProjectPaneGitHubToggleAction>,
131
+ input: {
132
+ readonly label: string;
133
+ readonly nodeId: string;
134
+ readonly threads: readonly ProjectPaneGitHubReviewThread[];
135
+ readonly expandedNodeIds: ReadonlySet<string>;
136
+ },
137
+ ): void {
138
+ const commentCount = countComments(input.threads);
139
+ const expanded = input.expandedNodeIds.has(input.nodeId);
140
+ const groupGlyph = expanded ? '▼' : '▶';
141
+ pushLine(
142
+ lines,
143
+ actionByRelativeLineIndex,
144
+ `${groupGlyph} ${input.label} (${String(input.threads.length)} threads, ${String(commentCount)} comments)`,
145
+ toggleAction(input.nodeId),
146
+ );
147
+ if (!expanded) {
148
+ return;
149
+ }
150
+ if (input.threads.length === 0) {
151
+ pushLine(lines, actionByRelativeLineIndex, ' (none)', null);
152
+ return;
153
+ }
154
+
155
+ for (const thread of input.threads) {
156
+ const nodeId = threadNodeId(thread);
157
+ const threadExpanded = input.expandedNodeIds.has(nodeId);
158
+ const threadGlyph = threadExpanded ? '▼' : '▶';
159
+ const firstAuthor = thread.comments[0]?.authorLogin ?? null;
160
+ const metadataParts: string[] = [];
161
+ if (thread.isOutdated) {
162
+ metadataParts.push('outdated');
163
+ }
164
+ if (thread.isResolved && thread.resolvedByLogin !== null) {
165
+ metadataParts.push(`resolved by ${formatAuthor(thread.resolvedByLogin)}`);
166
+ }
167
+ const metadataSuffix = metadataParts.length === 0 ? '' : `, ${metadataParts.join(', ')}`;
168
+ pushLine(
169
+ lines,
170
+ actionByRelativeLineIndex,
171
+ ` ${threadGlyph} ${formatAuthor(firstAuthor)} (${String(thread.comments.length)} comments${metadataSuffix})`,
172
+ toggleAction(nodeId),
173
+ );
174
+ if (!threadExpanded) {
175
+ continue;
176
+ }
177
+ if (thread.comments.length === 0) {
178
+ pushLine(lines, actionByRelativeLineIndex, ' - (no comments)', null);
179
+ continue;
180
+ }
181
+ for (const comment of thread.comments) {
182
+ const preview = commentPreview(comment.body);
183
+ pushLine(
184
+ lines,
185
+ actionByRelativeLineIndex,
186
+ ` - ${formatAuthor(comment.authorLogin)}: ${preview}`,
187
+ null,
188
+ );
189
+ }
190
+ }
191
+ }
192
+
193
+ export function buildProjectPaneGitHubReviewLines(
194
+ input: BuildProjectPaneGitHubReviewLinesInput,
195
+ ): BuildProjectPaneGitHubReviewLinesResult {
196
+ const lines: string[] = [];
197
+ const actionByRelativeLineIndex: Record<number, ProjectPaneGitHubToggleAction> = {};
198
+
199
+ pushLine(lines, actionByRelativeLineIndex, 'github review', null);
200
+
201
+ const branchName = input.review.branchName?.trim() ?? '';
202
+ const branchSource = input.review.branchSource;
203
+ const sourceLabel = branchSource === null ? '' : ` (${branchSource})`;
204
+ pushLine(
205
+ lines,
206
+ actionByRelativeLineIndex,
207
+ `branch ${branchName.length > 0 ? branchName : '(none)'}${sourceLabel}`,
208
+ null,
209
+ );
210
+
211
+ if (input.review.status === 'loading') {
212
+ pushLine(lines, actionByRelativeLineIndex, 'status loading GitHub review data…', null);
213
+ return {
214
+ lines,
215
+ actionByRelativeLineIndex,
216
+ };
217
+ }
218
+
219
+ if (input.review.status === 'error') {
220
+ const message =
221
+ input.review.errorMessage === null
222
+ ? 'unknown error'
223
+ : sanitizeInlineText(input.review.errorMessage);
224
+ pushLine(lines, actionByRelativeLineIndex, `status error ${message}`, null);
225
+ return {
226
+ lines,
227
+ actionByRelativeLineIndex,
228
+ };
229
+ }
230
+
231
+ const pr = input.review.pr;
232
+ if (pr === null) {
233
+ pushLine(lines, actionByRelativeLineIndex, 'pr none for tracked branch', null);
234
+ return {
235
+ lines,
236
+ actionByRelativeLineIndex,
237
+ };
238
+ }
239
+
240
+ const stateLabel = prStateLabel(pr);
241
+ pushLine(
242
+ lines,
243
+ actionByRelativeLineIndex,
244
+ `pr #${String(pr.number)} ${stateLabel} ${sanitizeInlineText(pr.title)}`,
245
+ null,
246
+ );
247
+ pushLine(
248
+ lines,
249
+ actionByRelativeLineIndex,
250
+ `from ${pr.headBranch} -> ${pr.baseBranch} by ${formatAuthor(pr.authorLogin)}`,
251
+ null,
252
+ );
253
+
254
+ appendThreadGroup(lines, actionByRelativeLineIndex, {
255
+ label: 'open comments',
256
+ nodeId: OPEN_THREAD_GROUP_NODE_ID,
257
+ threads: input.review.openThreads,
258
+ expandedNodeIds: input.expandedNodeIds,
259
+ });
260
+ appendThreadGroup(lines, actionByRelativeLineIndex, {
261
+ label: 'resolved comments',
262
+ nodeId: RESOLVED_THREAD_GROUP_NODE_ID,
263
+ threads: input.review.resolvedThreads,
264
+ expandedNodeIds: input.expandedNodeIds,
265
+ });
266
+
267
+ return {
268
+ lines,
269
+ actionByRelativeLineIndex,
270
+ };
271
+ }
@@ -38,6 +38,7 @@ export function buildRenderRows(
38
38
  rightRows: readonly string[],
39
39
  perf: MuxPerfStatusRow,
40
40
  statusRowDetailText?: string,
41
+ showStatusRow = true,
41
42
  ): string[] {
42
43
  const rows: string[] = [];
43
44
  const separatorAnchor = `\u001b[${String(layout.separatorCol)}G`;
@@ -47,6 +48,9 @@ export function buildRenderRows(
47
48
  const right = rightRows[row] ?? ' '.repeat(layout.rightCols);
48
49
  rows.push(`${left}\u001b[0m${separatorAnchor}${MUTED_SEPARATOR}${rightAnchor}${right}`);
49
50
  }
51
+ if (!showStatusRow) {
52
+ return rows;
53
+ }
50
54
  const defaultStatus = `[mux] fps=${perf.fps.toFixed(1)} kb/s=${perf.kbPerSecond.toFixed(1)} render=${perf.renderAvgMs.toFixed(2)}/${perf.renderMaxMs.toFixed(2)}ms output=${perf.outputHandleAvgMs.toFixed(2)}/${perf.outputHandleMaxMs.toFixed(2)}ms loop.p95=${perf.eventLoopP95Ms.toFixed(1)}ms`;
51
55
  const statusText =
52
56
  statusRowDetailText === undefined || statusRowDetailText.length === 0