Skip to content

cmux-next: draw workspace status, progress and log in sidebar rows - #16431

Merged
teamleaderleo merged 7 commits into
feat-cmux-nextfrom
feat-cmux-next-sidebar-status
Oct 11, 2026
Merged

teamleaderleo merged 7 commits into
feat-cmux-nextfrom
feat-cmux-next-sidebar-status

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 1, 2026 •

Copy link
Copy Markdown
Collaborator

Workspace rows in cmux-next now draw what agents and scripts report with cmux workspace status|log|progress, the way classic's sidebar did. A workspace that reports something shows a block under its name: its status entries (icon and text in the entry's color, then "N more" past three), the newest log line with its level glyph, then the progress bar and its label. A workspace that reports nothing keeps its one-line row.

What changes

  • Data: none new. The base already mirrors workspace_status state into WorkspaceModel.status (state resources via SessionStateMirror). SidebarMapping maps it into SidebarWorkspace.reported, minus the ports and pr entries that have their own row elements.
  • Row: WorkspaceRowContent.status carries the block; SidebarLayoutMetrics sizes the row from it (one status line per line, plus the bar's slot). WorkspaceStatusView draws it under the name, and the row's progress bar sits in its slot before the label. Accessibility reads every entry, the log line and the label.
  • Defaults, "on when reported": a new sidebar.workspaceRow.log element. agentStatus, log and progress are now on by default, but they draw nothing until a workspace reports something, so quiet rows stay minimal. Each can still be turned off, globally or per workspace kind. The second line no longer repeats the entries the block draws.
  • Settings exports (schema, MDM manifest and docs) are regenerated on the fleet; the new strings are in all 21 catalog languages (en/ja translated, the rest needs_review).

Superseded

This PR's first version also added the delivery path (a session.events tracker, v2 line routing, a DaemonStore status map). feat-cmux-next now delivers the same state through SessionStateMirror, so the merge takes the base for all of that and this PR is UI only. It doesn't need #16819.

Not ported, as before: the "Show more" toggle, clickable URL and markdown entries, and classic's sidebar.showLog/showProgress/showCustomMetadata keys (the sidebar.workspaceRow.* toggles replace them).

Verification

  • Behavior test SidebarStatusBlockTests (CmuxNextAppTests): a store with one reporting and one quiet workspace, mapped and laid out under cmux.json settings. Red on a1bf038 (the merged base plus the test): the reporting row was 24 pt, the minimal height. Green on the head below, in the same fleet suite run.
  • God-file check against the merged base (457baf6): pass.
  • On head 81173c9: fleet Release compile BUILD SUCCEEDED (cmux-ci step e4079fa4c8dd), and fleet Swift suites passed 74 of 74, including SidebarStatusBlockTests and the settings export tests (step abcc0ba79a3b).
  • Not yet verified live on a tagged build.

Live verification

DEV build sbstat of 81173c9 on a capture mini. Codex (codex exec, the mini's own sign-in) ran in a cmux terminal of a new workspace and reported, through the cmux CLI, four status entries (build with hammer and #ff8800, tests with checkmark.circle and green, lint, docs), a warning log line and 40% "Linking" progress. The sidebar row drew Building, 412 passed, clean, "1 more", ⚠ 2 warnings and the progress bar with its label; workspace-2, which reported nothing, stayed one line. Setting sidebar.workspaceRow.log to false hid only the log line (the mini's config was restored afterwards); clearing the entries and progress shrank the row to its name and last log line.

Review subagent: nothing blocking. Noted: a placeholder row would still reserve the block's height (unlikely), VoiceOver reads the log line without its level, and the test does not cover "N more" or the log toggle alone.

Changelog

  • Added: cmux-next sidebar rows show the status, log line and progress that agents and scripts report with cmux workspace status|log|progress. Progress is now on by default, so a terminal's own OSC 9;4 progress and program or agent busy/paused marks also show on rows that report nothing else (the row stays one line).

🤖 Generated with Claude Code

The daemon already stores per-workspace status entries, progress and a
log (workspace_status.*) and the new CLI writes them
(`cmux workspace [<sel>] status|progress|log`), but the app never read
them: its WorkspaceStatusBoard was fed only by the deleted compat layer.

The app now opens one `session.events` stream per daemon connection
right after `subscribe` and keeps only its workspace_status changes:
the opening snapshot resets the store's status map, deltas upsert or
delete one workspace. Status-less deltas are dropped on the reader
thread, so they never wake the main actor. Status events bypass the
tree snapshot barrier (list-workspaces does not carry them), a stream
end reopens the stream within a small budget, and an inbox collapse
keeps one stale marker that asks for a fresh stream.

The transport routes v2 stream lines as events, and the stream open
never joins the FIFO that id-less raw errors resolve against.

Sidebar rows draw the old app's block under the title: up to three
entries (icon and text in the entry color) then "N more", the newest
log line with its level glyph, then the progress bar and its label.
Row height grows one status line per line plus the bar.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration
  • Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 4f4d2302-9ece-4b89-ae8c-25333cae297b

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

CI fast guards failed on 81173c96b0 (https://github.com/manaflow-ai/cmux/actions/runs/38134620520). It does not block the merge; a red guard merged into main breaks it for every open PR.
The log named no failed step; see the run.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally. This comment is updated in place on each push.

@blacksmith-sh

This comment has been minimized.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Unclear: web / react-apps-check failed: no known signature; failed step: Check webviews (Oxlint, Oxfmt, type check).

CI failed on 81173c96b0 (run 38134620520 attempt 1): 1 unknown.
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped.

Job Verdict Why
web / react-apps-check unknown no known signature; failed step: Check webviews (Oxlint, Oxfmt, type check)

Not re-run automatically: web / react-apps-check is not a machine failure.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

Status lines take at least their font's height, hex colors need their #,
a closed socket forgets its stream, and the placement and lifetime fakes
ignore the handshake's session.events request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Store/DaemonStore+Driver.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Store/DaemonStore+Driver.swift:64">
P2: This stale marker resets the session-events no-snapshot retry budget, allowing a daemon that repeatedly ends the stream to loop indefinitely whenever status traffic is dropped. Refresh the stream without resetting the budget; only a successfully received snapshot should refill it.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Views/WorkspaceStatusView.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Views/WorkspaceStatusView.swift:18">
P2: The progress-bar sublayers use top-origin coordinates, but this flipped view never marks its backing layer as geometry-flipped. Set the backing layer’s `isGeometryFlipped` to `true`, otherwise Core Animation can render the bar vertically mirrored relative to the labels.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

case .workspaceStatus(_, let stream):
guard !state.statusStale else { return }
state.statusStale = true
state.events.append(DaemonEventEnvelope(sequence: envelope.sequence, event: .workspaceStatus(.stale, stream: stream)))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This stale marker resets the session-events no-snapshot retry budget, allowing a daemon that repeatedly ends the stream to loop indefinitely whenever status traffic is dropped. Refresh the stream without resetting the budget; only a successfully received snapshot should refill it.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Store/DaemonStore+Driver.swift, line 64:

<comment>This stale marker resets the session-events no-snapshot retry budget, allowing a daemon that repeatedly ends the stream to loop indefinitely whenever status traffic is dropped. Refresh the stream without resetting the budget; only a successfully received snapshot should refill it.</comment>

<file context>
@@ -49,12 +51,17 @@ final class EventInbox: Sendable {
+        case .workspaceStatus(_, let stream):
+            guard !state.statusStale else { return }
+            state.statusStale = true
+            state.events.append(DaemonEventEnvelope(sequence: envelope.sequence, event: .workspaceStatus(.stale, stream: stream)))
         default:
             guard let transaction = envelope.event.clientTransactionID, state.echoes.insert(transaction).inserted else { return }
</file context>


override init(frame: NSRect) {
super.init(frame: frame)
wantsLayer = true

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The progress-bar sublayers use top-origin coordinates, but this flipped view never marks its backing layer as geometry-flipped. Set the backing layer’s isGeometryFlipped to true, otherwise Core Animation can render the bar vertically mirrored relative to the labels.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Views/WorkspaceStatusView.swift, line 18:

<comment>The progress-bar sublayers use top-origin coordinates, but this flipped view never marks its backing layer as geometry-flipped. Set the backing layer’s `isGeometryFlipped` to `true`, otherwise Core Animation can render the bar vertically mirrored relative to the labels.</comment>

<file context>
@@ -0,0 +1,158 @@
+
+    override init(frame: NSRect) {
+        super.init(frame: frame)
+        wantsLayer = true
+        for bar in [track, fill] {
+            bar.cornerCurve = .continuous
</file context>
Suggested change
wantsLayer = true
wantsLayer = true
layer?.isGeometryFlipped = true

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 existing issue remains and 6 new issues found across 36 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Resources/Localizable.xcstrings">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Resources/Localizable.xcstrings:3416">
P2: The consumer `Strings.statusMore` reads this key with `String(localized:defaultValue:)`, which does not perform printf-style formatting, so the `%lld` placeholders in the catalog values render literally ("%lld more") instead of the count. Wrap the localized string in `String(format:)` in the consumer, e.g. `String(format: String(localized: "sidebar.status.more", defaultValue: "\(value) more", bundle: .module), value)`, or drop the `%lld` placeholders here if formatting is not intended.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Tree/WorkspaceStatusSnapshot.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Tree/WorkspaceStatusSnapshot.swift:80">
P2: These four snapshot fields are required by resource-api-v2, but `decodeIfPresent` turns a partial stream payload into a valid reset and can erase the current status map. Require the keys while still allowing the required nullable fields to contain `null`, so malformed snapshots are discarded rather than applied.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Model/SidebarWorkspaceStatus.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Model/SidebarWorkspaceStatus.swift:45">
P2: `Progress.value` can bypass the documented `0...1` invariant after initialization because it is publicly writable. Make the setter private (or clamp every assignment) before the renderer uses it to size the fill layer.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Connection/DaemonConnection+SessionEvents.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Connection/DaemonConnection+SessionEvents.swift:63">
P2: A stream ending during the handshake loses recovery because `reopen()` runs while the connection is still `.connecting`, when `reopenSessionEvents` ignores it. Defer this reopen until the handshake publishes `.ready`, or retry it after the initial open completes.</violation>
</file>

<file name="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Views/WorkspaceStatusView.swift">

<violation number="1" location="Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Views/WorkspaceStatusView.swift:73">
P2: Each status line advances only `statusLineHeight` (`y += lineHeight`), but its label frame is sized to `labelHeight = max(statusLineHeight, ceil(subtitleFont.boundingRectForFont.height))` and centered on the slot. When the font's actual line height exceeds `statusLineHeight`, adjacent status lines overlap. Guarantee `labelHeight <= lineHeight` (e.g. clamp it) so multi-line status rows do not clip.</violation>
</file>

<file name="plans/cmux-next/cli-compat.md">

<violation number="1" location="plans/cmux-next/cli-compat.md:85">
P3: The updated `set_status` row says progress and log are superseded by `cmux workspace status|progress|log` (daemon `workspace_status.*`), but the adjacent `set_progress / clear_progress / log / clear_log / list_log / sidebar_state` row still classifies them as `impl (same store)`. Since the new command and the Decisions note cover progress and log as daemon state, update that row (separate the still-store-sidebar_state verb) to keep the compat table internally consistent.</violation>
</file>

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.

Re-trigger cubic

"en": {
"stringUnit": {
"state": "translated",
"value": "%lld more"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The consumer Strings.statusMore reads this key with String(localized:defaultValue:), which does not perform printf-style formatting, so the %lld placeholders in the catalog values render literally ("%lld more") instead of the count. Wrap the localized string in String(format:) in the consumer, e.g. String(format: String(localized: "sidebar.status.more", defaultValue: "\(value) more", bundle: .module), value), or drop the %lld placeholders here if formatting is not intended.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Resources/Localizable.xcstrings, line 3416:

<comment>The consumer `Strings.statusMore` reads this key with `String(localized:defaultValue:)`, which does not perform printf-style formatting, so the `%lld` placeholders in the catalog values render literally ("%lld more") instead of the count. Wrap the localized string in `String(format:)` in the consumer, e.g. `String(format: String(localized: "sidebar.status.more", defaultValue: "\(value) more", bundle: .module), value)`, or drop the `%lld` placeholders here if formatting is not intended.</comment>

<file context>
@@ -3406,6 +3406,137 @@
+        "en": {
+          "stringUnit": {
+            "state": "translated",
+            "value": "%lld more"
+          }
+        },
</file context>

public init(from decoder: any Decoder) throws {
let c = try decoder.container(keyedBy: CodingKeys.self)
workspaceID = try c.decode(ResourceID.self, forKey: .workspaceID)
entries = try c.decodeIfPresent([Entry].self, forKey: .entries) ?? []

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: These four snapshot fields are required by resource-api-v2, but decodeIfPresent turns a partial stream payload into a valid reset and can erase the current status map. Require the keys while still allowing the required nullable fields to contain null, so malformed snapshots are discarded rather than applied.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Tree/WorkspaceStatusSnapshot.swift, line 80:

<comment>These four snapshot fields are required by resource-api-v2, but `decodeIfPresent` turns a partial stream payload into a valid reset and can erase the current status map. Require the keys while still allowing the required nullable fields to contain `null`, so malformed snapshots are discarded rather than applied.</comment>

<file context>
@@ -0,0 +1,85 @@
+    public init(from decoder: any Decoder) throws {
+        let c = try decoder.container(keyedBy: CodingKeys.self)
+        workspaceID = try c.decode(ResourceID.self, forKey: .workspaceID)
+        entries = try c.decodeIfPresent([Entry].self, forKey: .entries) ?? []
+        progress = try c.decodeIfPresent(Progress.self, forKey: .progress)
+        logCount = try c.decodeIfPresent(Int.self, forKey: .logCount) ?? 0
</file context>


/// `value` in 0...1; nil draws an empty track (indeterminate).
public nonisolated struct Progress: Hashable, Sendable {
public var value: Double?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Progress.value can bypass the documented 0...1 invariant after initialization because it is publicly writable. Make the setter private (or clamp every assignment) before the renderer uses it to size the fill layer.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Model/SidebarWorkspaceStatus.swift, line 45:

<comment>`Progress.value` can bypass the documented `0...1` invariant after initialization because it is publicly writable. Make the setter private (or clamp every assignment) before the renderer uses it to size the fill layer.</comment>

<file context>
@@ -0,0 +1,133 @@
+
+    /// `value` in 0...1; nil draws an empty track (indeterminate).
+    public nonisolated struct Progress: Hashable, Sendable {
+        public var value: Double?
+        public var label: String?
+
</file context>
Suggested change
public var value: Double?
public private(set) var value: Double?

state.endsWithoutSnapshot += 1
return state.endsWithoutSnapshot <= Self.reopenBudget
}
if again { reopen() }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: A stream ending during the handshake loses recovery because reopen() runs while the connection is still .connecting, when reopenSessionEvents ignores it. Defer this reopen until the handshake publishes .ready, or retry it after the initial open completes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextDaemon/Connection/DaemonConnection+SessionEvents.swift, line 63:

<comment>A stream ending during the handshake loses recovery because `reopen()` runs while the connection is still `.connecting`, when `reopenSessionEvents` ignores it. Defer this reopen until the handshake publishes `.ready`, or retry it after the initial open completes.</comment>

<file context>
@@ -0,0 +1,89 @@
+                state.endsWithoutSnapshot += 1
+                return state.endsWithoutSnapshot <= Self.reopenBudget
+            }
+            if again { reopen() }
+            return false
+        case .unknown(let name, _) where name == "stream_item" || name == "stream_end":
</file context>

layoutBar(y: y, height: metrics.progressBarHeight)
y += metrics.progressBarHeight
}
labels[index].frame = NSRect(x: 0, y: y - (labelHeight - lineHeight) / 2, width: bounds.width, height: labelHeight)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Each status line advances only statusLineHeight (y += lineHeight), but its label frame is sized to labelHeight = max(statusLineHeight, ceil(subtitleFont.boundingRectForFont.height)) and centered on the slot. When the font's actual line height exceeds statusLineHeight, adjacent status lines overlap. Guarantee labelHeight <= lineHeight (e.g. clamp it) so multi-line status rows do not clip.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At Packages/macOS/CmuxNext/Sources/CmuxNextSidebar/Views/WorkspaceStatusView.swift, line 73:

<comment>Each status line advances only `statusLineHeight` (`y += lineHeight`), but its label frame is sized to `labelHeight = max(statusLineHeight, ceil(subtitleFont.boundingRectForFont.height))` and centered on the slot. When the font's actual line height exceeds `statusLineHeight`, adjacent status lines overlap. Guarantee `labelHeight <= lineHeight` (e.g. clamp it) so multi-line status rows do not clip.</comment>

<file context>
@@ -0,0 +1,158 @@
+                layoutBar(y: y, height: metrics.progressBarHeight)
+                y += metrics.progressBarHeight
+            }
+            labels[index].frame = NSRect(x: 0, y: y - (labelHeight - lineHeight) / 2, width: bounds.width, height: labelHeight)
+            y += lineHeight
+        }
</file context>

Comment thread plans/cmux-next/cli-compat.md Outdated
| agent.resolve_delivery_target | 0 | 0 | yes | hooks | impl by surface_id; pid routing answers "No live delivery target" |
| agent.hook.*, surface.resume.*, workspace.set_auto_title, surface.sync_codex_native_title, agent.hibernation.* | 0 | 0 | yes | hooks | unsup: agent state moves to cmux-tui report-agent |
| v1 set_status / clear_status / list_status | 3/1 (CLI) | 2 | yes | set-status, … | impl: in-memory per workspace (bounded), not rendered in the sidebar yet |
| v1 set_status / clear_status / list_status | 3/1 (CLI) | 2 | yes | set-status, … | superseded: `cmux workspace status\|progress\|log` (daemon state), rendered in the sidebar row |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The updated set_status row says progress and log are superseded by cmux workspace status|progress|log (daemon workspace_status.*), but the adjacent set_progress / clear_progress / log / clear_log / list_log / sidebar_state row still classifies them as impl (same store). Since the new command and the Decisions note cover progress and log as daemon state, update that row (separate the still-store-sidebar_state verb) to keep the compat table internally consistent.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. When an issue isn't valid or won't be fixed in this PR, reply in its thread with the reason and then resolve the thread. At plans/cmux-next/cli-compat.md, line 85:

<comment>The updated `set_status` row says progress and log are superseded by `cmux workspace status|progress|log` (daemon `workspace_status.*`), but the adjacent `set_progress / clear_progress / log / clear_log / list_log / sidebar_state` row still classifies them as `impl (same store)`. Since the new command and the Decisions note cover progress and log as daemon state, update that row (separate the still-store-sidebar_state verb) to keep the compat table internally consistent.</comment>

<file context>
@@ -82,7 +82,7 @@ Usage columns: tests_v2 calls/files, skills mentions (via the CLI verb), and whe
 | agent.resolve_delivery_target | 0 | 0 | yes | hooks | impl by surface_id; pid routing answers "No live delivery target" |
 | agent.hook.*, surface.resume.*, workspace.set_auto_title, surface.sync_codex_native_title, agent.hibernation.* | 0 | 0 | yes | hooks | unsup: agent state moves to cmux-tui report-agent |
-| v1 set_status / clear_status / list_status | 3/1 (CLI) | 2 | yes | set-status, … | impl: in-memory per workspace (bounded), not rendered in the sidebar yet |
+| v1 set_status / clear_status / list_status | 3/1 (CLI) | 2 | yes | set-status, … | superseded: `cmux workspace status\|progress\|log` (daemon state), rendered in the sidebar row |
 | v1 set_progress / clear_progress / log / clear_log / list_log / sidebar_state | CLI | 1–2 | | set-progress, log, sidebar-state | impl (same store; sidebar_state reads cwd/branch from cmux-tui) |
 | v1 set_agent_pid / clear_agent_pid | 0 | 0 | yes | hooks | impl (stored) |
</file context>

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review: a fresh review agent read the change at 94aa790. The wire matches the cmux-tui server (session.events lines, workspace_status snapshot and delta shapes, stream ids, stream.cancel).

Fixed in af90c56:

  • Two existing fake daemons advertise terminal-reap-v1 and log every v2 request, so the new session.events open would have broken PlacementEnvTests and TerminalLifetimeTests. They now skip it.
  • A custom sidebar row height could shrink the step between status lines to zero or below, stacking the lines on top of each other. Status lines now take at least their font's height.
  • Hex colors need their #, so a palette-shaped name like facade isn't read as RGB.
  • A closed socket forgets its stream, so the next connection doesn't cancel a stream on the wrong socket.

Left:

  • A stream_end that arrives during the handshake isn't reopened until the next reconnect.
  • Under sustained event overflow, every snapshot becomes stale again, so the app keeps asking for snapshots while the load lasts.

CI: the red checks are inherited from the feat-cmux-next-acpmux base; see the "Stacked on #16174" section.

Head: af90c56

Base automatically changed from feat-cmux-next-acpmux to feat-cmux-next October 3, 2026 01:21
@azooz2003-bit azooz2003-bit reopened this Oct 6, 2026
@cursor

cursor Bot commented Oct 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@cursor

cursor Bot commented Oct 6, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Superseded on feat-cmux-next: 758fef6 ("cmux-next: mirror the daemon's state resources from session.events") added SessionStateMirror.workspaceStatus fed by the session.events snapshot and workspace_status upserts/deletes, and CmuxNextBridge/SidebarMapping.swift now draws the daemon's workspace status line (statusLine) and reported progress (SidebarWorkspace.progress) in sidebar rows. This branch's delivery layer (DaemonConnection+SessionEvents, DaemonStore+WorkspaceStatus, WorkspaceStatusBoard) no longer fits base, which is ~14.6k commits ahead. If the workspace log line is still wanted in the row, it should be a small new PR on top of SessionStateMirror. Leaving open for a human to close.

teamleaderleo and others added 5 commits October 11, 2026 03:48
Base now delivers workspace status through SessionStateMirror into
WorkspaceModel.status, so this PR's daemon/transport half is superseded.
Resolved by taking the base tree; the sidebar UI is re-ported on top in
follow-up commits. --no-verify: merge commit of base content only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Red on the merged base: a workspace that reports status, a log line and
progress still draws the minimal one-line row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Re-port #16431's sidebar UI on the base's data path: WorkspaceModel.status
(state resources via SessionStateMirror) maps into SidebarWorkspace.reported,
minus the ports and pr entries other elements show. WorkspaceRowContent
carries classic's status block (entries with icon and color, "N more", the
newest log line, the progress label) and SidebarLayoutMetrics sizes the row
from it; the row view draws it under the name with the progress bar in its
slot before the label.

Defaults ("on when reported"): new `log` element; agentStatus, log and
progress now show by default but draw nothing until a workspace reports
something, so quiet rows stay minimal. The second line no longer repeats
the entries the block draws. Localized in every catalog locale; the
settings page strings are regenerated.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
From the fleet (export-settings-artifacts.sh on 21eaf58): the new
sidebar.workspaceRow.log key and agentStatus/log/progress on by default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- regenerated webviews/src/pages/settings/generated/strings.json

Autofix-Run: https://github.com/manaflow-ai/cmux/actions/runs/38134544040
@github-actions

Copy link
Copy Markdown
Contributor

Gallery

Review in feed

601 states changed: pages.settings/general-group-2, pages.settings/appearance-group-8, pages.settings/general-group-9, pages.settings-motion/play-reset-secondlineorder, agent-pane.transcript/shell-grouped-commands, ... · 2 new states · 38 broken states · 41 play checks failed

Diff page and renders (the run's gallery-pr artifact)

State Before · after
pages.settings/general-group-2 (Apple System Colors, webkit)
pages.settings/appearance-group-8 (Apple System Colors, webkit)
pages.settings/general-group-9 (Apple System Colors, chromium)
pages.settings/appearance-group-8 (Apple System Colors, webkit)
pages.settings-motion/play-reset-secondlineorder (Apple System Colors Light, chromium)
pages.settings-motion/play-reset-secondlineorder (Apple System Colors Light, webkit)

595 more on the diff page.

Live preview (follows this branch; start it with scripts/gallery-live.sh up <branch> from an hq checkout):

  • pages.settings/general-group-2: /wt/feat-cmux-next-sidebar-status/?entry=pages.settings#/pages.settings/general-group-2
  • pages.settings/appearance-group-8: /wt/feat-cmux-next-sidebar-status/?entry=pages.settings#/pages.settings/appearance-group-8
  • pages.settings/general-group-9: /wt/feat-cmux-next-sidebar-status/?entry=pages.settings#/pages.settings/general-group-9
  • pages.settings-motion/play-reset-secondlineorder: /wt/feat-cmux-next-sidebar-status/?entry=pages.settings-motion#/pages.settings-motion/play-reset-secondlineorder
  • agent-pane.transcript/shell-grouped-commands: /wt/feat-cmux-next-sidebar-status/?entry=agent-pane.transcript#/agent-pane.transcript/shell-grouped-commands
  • pages.diff/unified: /wt/feat-cmux-next-sidebar-status/?entry=pages.diff#/pages.diff/unified
  • 116 more on the diff page

Play checks failed (0 px anchor movement, 0 layout shift, no frame over 33 ms unless the entry gives a reason):

  • agent-pane.composer-pickers/model-menu (Apple System Colors, webkit): step 1 click button "Model": settle latency 327.0 ms (limit 250 ms)
  • ui.disclosure/keyboard (Apple System Colors Light, webkit): step 2 press Space: anchor .disclosure-gallery-receipt moved 92.0 px (limit 0) · step 3 press Enter: anchor .disclosure-gallery-receipt moved 92.0 px (limit 0)
  • agent-pane.changes-options-menu/keyboard (Apple System Colors Light, webkit): play: waitFor did not hold within 5000 ms
  • agent-pane.changes-scope-menu/open (Apple System Colors, webkit): play: waitFor did not hold within 5000 ms
  • agent-pane.start-folder/home-question (Apple System Colors Light, webkit): play: no element for menuitemradio "/\/Users\/you$/"
  • agent-pane.start-folder/home-question (Apple System Colors Light, webkit): play: no element for menuitemradio "/\/Users\/you$/"
  • 205 more on the diff page

375 nondeterministic states differed from a second render of the same head (a clock or fixture leak) and are not counted as changes.

4204 unchanged · base 457baf6 · head 81173c9

@teamleaderleo
teamleaderleo merged commit 116a7ba into feat-cmux-next Oct 11, 2026
127 of 132 checks passed
@teamleaderleo
teamleaderleo deleted the feat-cmux-next-sidebar-status branch October 11, 2026 12:13
teamleaderleo added a commit that referenced this pull request Oct 11, 2026
Keeps the row status block (#16431) beside expanded rows: an expanded row
leaves the block off (its second line shows the status), and the row height
adds the block's height to the line count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants