Skip to content

cmux-next: dock columns keep an agent chat role (dock-column-role-v1) - #18169

Merged
teamleaderleo merged 9 commits into
feat-cmux-nextfrom
next-dock-chat-role
Oct 7, 2026
Merged

teamleaderleo merged 9 commits into
feat-cmux-nextfrom
next-dock-chat-role

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 7, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

A dock column can now carry a role, and the only role is agent_chat. This is groundwork for section D of the 2026-10-06 call: the agent chat becomes a docked region on the left (like the Codex app), and the app needs to know which dock is the chat dock.

The role is an explicit, persisted flag rather than inferred from the column's tabs. Inference breaks when someone puts chats in a left dock by hand, or when a chat leaves the dock. An explicit role makes Dock/Undock and restart restore unambiguous.

  • Daemon: ColumnDock gains role: Option<DockRole>. set-column-dock takes an optional role, and move-tab-to-column's dock pin carries one. The role lives and dies with the pin: undocking drops it. An unknown role is rejected (InvalidArgument, field role). Stored roles decode leniently, so a newer role read by an older daemon becomes none instead of failing. It is advertised as dock-column-role-v1.
  • Storage: side docks already persist as the JSON dock in the registry viewport record, so the role rides along without a SQL migration.
  • Not covered: the resource API's column.update has no role.
  • SDK: sdk-schema.json and commands.md describe the field. Bindings were regenerated in all 8 languages.
  • App: DockSnapshot, SetColumnDockRequest and the move-tab-to-column pin encode the role. CmuxNextLayout.DockColumn maps it, and DaemonCapabilities.dockColumnRole is optional.

No behavior changes yet. A follow-up PR uses the role to open tools from the chat dock in the strip.

Testing

The tests were committed red before the fix (513ffb1). They are wire-level, so they compile on the old code.

Rust (./scripts/verify-cmux-tui-hosted.sh --filter _role on exact heads):

Commit Result
513ffb1 (red) exactly the 5 new tests failed: dock_column_rejects_an_unknown_role, dock_column_role_capability_is_advertised, dock_column_role_is_kept_with_the_pin_and_dropped_with_it, move_tab_to_column_pins_the_new_column_with_its_role, a_registry_viewport_keeps_the_dock_role
763a51f (green) all 5 passed in test (linux); macOS lint and tests, Rust MSRV (1.91) and Go pane SDK passed

On the green run, lint (linux) failed only on the Rust god-file check. That failure is already on feat-cmux-next (acpmux profiles.rs and requests.rs are over the limit). The release-path dogfood artifacts / build aarch64-apple-darwin job was refused by the runner hook because a fleet build was waiting for the host. That is infra, not a test result.

After merging permanent-dock-v1 from base (21a8ef7, Lawrence's permanent docked column): ColumnDock and set-column-dock carry both role and permanent, and both capabilities are advertised. ./scripts/verify-cmux-tui-hosted.sh --filter dock_column on head 0c2a49f passed: lint (linux), test (linux) (the role tests and the permanent-dock tests ran) and macOS lint and tests (run).

Swift: scripts/measure/suite-runner.sh on a fleet runner.

Commit Result
red EncodingTests.dockRequestsCarryTheDockRole and DockColumnMappingTests.theAgentChatRoleSurvivesTheLayout failed
green passed: EncodingTests, DockColumnMappingTests, DaemonCapabilityExportTests, DockColumnCapabilityTests

Local: the SDK schema and codegen drift checks passed, and verify-local.py --only swift-syntax --swift-changed passed. The full verify-local.py fails on localization, localization-defaults and package-groups. Those failures come from files this PR does not touch (string catalogs, the mismatch list, the workspace package groups).

User-facing strings: none.

Not run: a review sub-agent (lane rule: no sub-agents). No live check, because nothing visible changes.

Changelog

none

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.


Summary by cubic

Fixes dock column identification by adding an optional role to dock columns, with agent_chat the only role, so the app can tell which dock is the chat column without inferring it from its tabs.

  • The role is set with the pin via set-column-dock and move-tab-to-column, and dropped when the column is unpinned.
  • It is stored inside the existing dock JSON in the registry record, so no SQL migration is needed.
  • The daemon advertises dock-column-role-v1; unknown roles are rejected with InvalidArgument, and an unknown role in a stored record reads as no role instead of failing.
  • Spec and SDK bindings for all 8 languages were regenerated.
  • There are no behavior changes yet; a follow-up PR uses the role to keep new tools out of the chat dock.

Written for commit d636ad8. Summary will update on new commits.

View guided diff Turn on auto-fix


Note

Medium Risk
Touches persisted layout state and mux protocol fields, but the capability is optional and older daemons/clients ignore unknown roles; runtime layout rules are unchanged until follow-up UI logic lands.

Overview
Introduces dock-column-role-v1, an optional role on docked viewport columns so clients can mark the agent chat column (agent_chat) without inferring it from tab content.

The daemon and wire protocol gain role on set-column-dock, move-tab-to-column's dock pin, and Screen.columns[].dock. The role is kept with the pin, cleared on undock or when re-pinning without a role, rejected for unknown values, and decoded leniently in stored viewport JSON. ColumnDock::new and related call sites were updated to carry the new field alongside existing dock metadata.

Cmux Next maps the role through DockSnapshot, DockColumn, DockRole, and LayoutMapping, and advertises dockColumnRole as an optional daemon capability. SDK schema, commands.md, and generated bindings (all languages) were regenerated; IR SHA bumped.

No product behavior uses the role yet—that is left to a follow-up (e.g. keeping new tools out of the chat dock).

Reviewed by Cursor Bugbot for commit d636ad8. Bugbot is set up for automated code reviews on this repo. Configure here.

teamleaderleo and others added 4 commits October 6, 2026 18:07
Red: set-column-dock and move-tab-to-column drop role, identify does not
advertise dock-column-role-v1, the registry record drops it, and the app
never sends it back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
cmux-tui: ColumnDock gains an optional role (agent_chat), set with the pin
by set-column-dock and move-tab-to-column, journaled and restored with it,
dropped with it, and read as no role when unknown. identify advertises
dock-column-role-v1. Spec and generated bindings updated.

cmux next: DockSnapshot, the dock requests and the layout's DockColumn
carry the role; no behavior uses it yet.

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

coderabbitai Bot commented Oct 7, 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: 661ce335-3420-4741-aa4f-1ca7cd5a1eaf

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
  • Autopilot · 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.

@blacksmith-sh

This comment has been minimized.

@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Not verified: macOS jobs did not run: compile and app tests were skipped on d636ad8b55; ci-status is green without them.

CI passes on d636ad8b55 (run 37618181470 attempt 1).
macOS jobs did not run: compile and app tests were skipped: Fast static checks skipped (the macos job needs both to succeed). Re-run CI once they pass, before merging.

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.

@lawrencecchen

Copy link
Copy Markdown
Contributor

Review (correctness read, nx-docked-column lane). One concrete defect:

The agent_chat role is lost when a person re-docks the chat column. set-column-dock replaces the whole ColumnDock, and an omitted role parses to None (parse_column_dock). The existing app paths never send a role: DockDefaults.plan builds DockColumn(edge: chosen, mode: mode) for Dock Column / Dock Column Left|Right / Float Column, and ColumnDocking.apply sends that through LayoutMapping.snapshot. Run Float Column, or Dock Column Right, on the chat dock: the dock stays, but its role becomes none, and #18170 then treats it as a plain dock and opens tools inside it. column.update (resource API, parse_column_dock(..., None)) has the same effect, as the description notes.

Suggested fix: when the column is already docked and the request omits role, keep the current role (an explicit undock still drops it). Alternatively, have DockDefaults.plan copy column.dock?.role into the new pin. A daemon test: chat dock -> set-column-dock {mode: overlay} -> role is still agent_chat.

…hat-role

# Conflicts:
#	cmux-tui/bindings/cpp/.cmux-sdk-manifest.json
#	cmux-tui/bindings/cpp/include/cmux/raw/generated/models.hpp
#	cmux-tui/bindings/go/raw/.cmux-sdk-manifest.json
#	cmux-tui/bindings/go/raw/generated_commands.go
#	cmux-tui/bindings/go/raw/generated_events.go
#	cmux-tui/bindings/go/raw/generated_metadata.go
#	cmux-tui/bindings/go/raw/generated_presence_test.go
#	cmux-tui/bindings/go/raw/generated_types.go
#	cmux-tui/bindings/java/src/com/cmux/raw/.cmux-sdk-manifest.json
#	cmux-tui/bindings/java/src/com/cmux/raw/Protocol.java
#	cmux-tui/bindings/python/cmux/raw/_generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/python/cmux/raw/_generated/_schema.py
#	cmux-tui/bindings/python/cmux/raw/_generated/metadata.py
#	cmux-tui/bindings/rust/src/generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/rust/src/generated/commands.rs
#	cmux-tui/bindings/rust/src/generated/events.rs
#	cmux-tui/bindings/rust/src/generated/metadata.rs
#	cmux-tui/bindings/rust/src/generated/mod.rs
#	cmux-tui/bindings/rust/src/generated/types.rs
#	cmux-tui/bindings/typescript/src/raw/generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/typescript/src/raw/generated/commands.ts
#	cmux-tui/bindings/typescript/src/raw/generated/events.ts
#	cmux-tui/bindings/typescript/src/raw/generated/index.ts
#	cmux-tui/bindings/typescript/src/raw/generated/metadata.ts
#	cmux-tui/bindings/typescript/src/raw/generated/types.ts
#	cmux-tui/bindings/zig/src/raw/generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/zig/src/raw/generated/protocol.zig
#	cmux-tui/spec/commands.md

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 063fc3e. Configure here.

Comment thread cmux-tui/crates/cmux-tui-core/src/mux/dock_columns.rs Outdated
…hat-role

# Conflicts:
#	cmux-tui/bindings/cpp/.cmux-sdk-manifest.json
#	cmux-tui/bindings/cpp/include/cmux/raw/generated/models.hpp
#	cmux-tui/bindings/cpp/src/raw/generated/protocol.cpp
#	cmux-tui/bindings/go/raw/.cmux-sdk-manifest.json
#	cmux-tui/bindings/go/raw/generated_commands.go
#	cmux-tui/bindings/go/raw/generated_events.go
#	cmux-tui/bindings/go/raw/generated_metadata.go
#	cmux-tui/bindings/go/raw/generated_presence_test.go
#	cmux-tui/bindings/go/raw/generated_types.go
#	cmux-tui/bindings/java/src/com/cmux/raw/.cmux-sdk-manifest.json
#	cmux-tui/bindings/java/src/com/cmux/raw/Protocol.java
#	cmux-tui/bindings/java/src/com/cmux/raw/SetColumnDockRequest.java
#	cmux-tui/bindings/python/cmux/raw/_generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/python/cmux/raw/_generated/_schema.py
#	cmux-tui/bindings/python/cmux/raw/_generated/client.py
#	cmux-tui/bindings/python/cmux/raw/_generated/metadata.py
#	cmux-tui/bindings/python/cmux/raw/_generated/models.py
#	cmux-tui/bindings/rust/src/generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/rust/src/generated/commands.rs
#	cmux-tui/bindings/rust/src/generated/events.rs
#	cmux-tui/bindings/rust/src/generated/metadata.rs
#	cmux-tui/bindings/rust/src/generated/mod.rs
#	cmux-tui/bindings/rust/src/generated/types.rs
#	cmux-tui/bindings/typescript/src/raw/generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/typescript/src/raw/generated/commands.ts
#	cmux-tui/bindings/typescript/src/raw/generated/events.ts
#	cmux-tui/bindings/typescript/src/raw/generated/index.ts
#	cmux-tui/bindings/typescript/src/raw/generated/metadata.ts
#	cmux-tui/bindings/typescript/src/raw/generated/types.ts
#	cmux-tui/bindings/zig/src/raw/generated/.cmux-sdk-manifest.json
#	cmux-tui/bindings/zig/src/raw/generated/protocol.zig
#	cmux-tui/crates/cmux-tui-core/src/model/layout_columns.rs
#	cmux-tui/crates/cmux-tui-core/src/mux/dock_columns.rs
#	cmux-tui/crates/cmux-tui-core/src/mux/tests/column_update.rs
#	cmux-tui/crates/cmux-tui-core/src/mux/tests/dock_columns.rs
#	cmux-tui/crates/cmux-tui-core/src/server.rs
#	cmux-tui/crates/cmux-tui-core/src/server/capabilities.rs
#	cmux-tui/crates/cmux-tui-core/src/server/dock_columns_tests.rs
#	cmux-tui/crates/cmux-tui-core/src/workspace_registry/resource_store/screen_rows.rs
#	cmux-tui/crates/cmux-tui-core/src/workspace_registry/resource_store/viewport.rs
#	cmux-tui/spec/sdk-schema.json
teamleaderleo and others added 3 commits October 7, 2026 00:51
@blacksmith-sh

blacksmith-sh Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Found 1 test failure on Blacksmith runners:

Failure

Test View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo
teamleaderleo merged commit ef830a5 into feat-cmux-next Oct 7, 2026
96 of 115 checks passed
@teamleaderleo
teamleaderleo deleted the next-dock-chat-role branch October 7, 2026 13:31
lawrencecchen added a commit that referenced this pull request Oct 10, 2026
… before cx-x7pl [cx-tqes]

move_tab_to_column_pins_the_new_column_with_its_role (added with
dock-column-role-v1, ef830a5 #18169) read the new column at index 1:
move-tab-to-column with no anchor put it after the last column. #18931
(5266485, cx-x7pl) changed that on purpose: a column pinned left by
the move now leads the order, so undocking the agent chat dock scrolls it
in on the left. The pin and its role are still written (the column is at
index 0 now); only the old position is gone. #18710 (a0ddb9c) is not
the cause: the moved column has one pane, which the chat-dock split rule
allows.

The test is an in-process unit test that asserts the removed order, so it
is deleted, not fixed (no-unit-tests rule). The daemon behavior test
tests/cli/left_dock_undock.rs (#18931) now moves the tab with role
agent_chat and asserts that the new column leads the order with
{edge: left, mode: docked, role: agent_chat}, so the role pin keeps a
check at the socket boundary.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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