Skip to content

Picker: anchor the model control below every composer - #26551

Merged
teamleaderleo merged 13 commits into
feat-cmux-nextfrom
lane/nx-picker-placement
Oct 28, 2026
Merged

teamleaderleo merged 13 commits into
feat-cmux-nextfrom
lane/nx-picker-placement

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

In the Codex composer and parts of New Tab, the model control sat inside the prompt box while the Claude chat put it underneath. The same model, mode, and effort control group now stays in the quiet footer in a new or existing chat, in either composer look. The Codex look keeps its own Send and Stop behavior; the plain-footer Debug setting still changes the row's styling. #26512 governs the menu's harness rail placement; this PR governs the composer's control anchor.

Leo, 2026-10-28: “do we want this at the top or at the bottom? ... I don't think it makes sense for there to be inconsistent placements across things.” The chosen reference is Claude desktop's composer-demo-ready.png: model and effort are quiet controls under the box, with our glass and colors retained.

Gallery evidence

Paired gallery fixture captures at 760 × 600, light and dark, from the initial base 7d3a7ccc3e3f73cc0a1f4c274857a477d5ce7cd0 and initial implementation 3d9060b41cf96b467fd97d4e23817b5db49d4562. The initial implementation captures are preserved below for before/after comparison:

Surface Before light After light Before dark After dark
Existing chat, Claude before chat claude light after chat claude light before chat claude dark after chat claude dark
Existing chat, Codex before chat codex light after chat codex light before chat codex dark after chat codex dark
New Tab, Claude before newtab claude light after newtab claude light before newtab claude dark after newtab claude dark
New Tab, Codex before newtab codex light after newtab codex light before newtab codex dark after newtab codex dark

React captures before final token cleanup

At head cd01633f0bcfdf80c04e2453521abfb069f751f1 on base af913f8f40638f8d7732575f89a8b03fc160e3ab, Chromium rendered the actual React gallery in a 760 × 600 pane. The chat Codex dots occupy y=512–536, after the action row ends at y=500, inside the box ending at y=536.

Surface Light Dark
Chat, Claude Chat, Claude light Chat, Claude dark
Chat, Codex Chat, Codex light Chat, Codex dark
New Tab, Claude New Tab, Claude light New Tab, Claude dark
New Tab, Codex New Tab, Codex light New Tab, Codex dark

Validation

  • Test-first commit 69ec39140bf0ba207b66c855ef6a64ccde3cf69e: CMUX_BROWSER_TESTS=1 bun test test/composer-look-dots.test.ts ran in Chromium with 4 passed and 3 placement failures on the base behavior.
  • At captured head cd01633f0bcfdf80c04e2453521abfb069f751f1, six independent-review regressions were reproduced red-first: Claude/Codex box-grid inversion, a 7px Codex wrapper collision, Classic New Tab footer losing its fit observer after Agent → Terminal → Agent, the actual 24px Codex dots overlapping the action row by 8px, the 20-line Markdown draft footer overflowing a 400px pane by 8px, and the shell textarea overlapping the action row by 35px. All are green after the fixes; the short-pane footer now ends at y=392, and the shell field stays above the actions.
  • At final review head f7afb1c8d9fb99ed9e2c0102ad33b3b81f0c3665 on base af913f8f40638f8d7732575f89a8b03fc160e3ab, the focused Chromium/layout suite passed 37 tests and 174 assertions across composer-footer-plain, composer-look-dots, new-tab-no-entry-classic, and new-tab-composer-layout. The final patch tokenizes the new footer minimum height, keeps its original 42px floor, restores the base tray reservation selector, and makes the boundary test account for the existing 5px alignment margin while still checking overlap and viewport clipping. Design-token and type-scale ratchets, Vite+ lint/format/typecheck, git diff --check, and scripts/cmux-next/prepush-gate.py pass.
  • Focused production gallery comparison on immutable base af913f8f and the final tree: both Claude/Codex permission-pill plays fail identically on base and head (no element for .acpmux-access-trigger); the controls-single-row and new-tab-default plays now both pass on the head at 280, 360, and 480 px. Before the gallery fixture repair, the former timed out and the latter reported the old inside-box assertion. The final fixture asserts the shared footer without changing UI behavior.
  • Classic NewTabPage now uses the same footer anchor: its model/mode group is outside the card's location row, in .acpmux-newtab-foot, with the same ComposerFoot and fit hook.
  • Vite+ format, lint (0 errors), and type check pass. scripts/cmux-next/prepush-gate.py reports no new violations.

Observed / Not run

The Chromium gallery and tests ran on gcp-agent-lane-1. The native app has not been built or launched on that host; native compile and captures belong to fleet CI.

Changelog

Changed: The composer model control stays below the prompt box across chat, New Tab, and both looks.

Agent session: agent session

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-l83rm5 created for this PR by the cmux coordinator.

@github-actions github-actions Bot added the risk:normal Risk tier (docs/ci/risk-tiers.md) label Oct 28, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, next-review): SHIP at 3d9060b

No blocking findings in the supplied diff and surrounding files. Tests were not independently run.

Automatic approval review rejected additional repository reads because approval is disabled, limiting review to the supplied files.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review f7afb1c: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr26551 -f ref=lane/nx-picker-placement -f platform=macos -f backend_mode=local

Unclear: web / react-apps-check failed: no known signature; failed step: Check webview test shards. This PR merged before its CI finished: fix forward on main.

CI failed on f7afb1c8d9 (run 40661461738 attempt 1): 4 code, 1 unknown.

Job Verdict Why
web / react-apps-base-check (3) code a web test failed
web / react-apps-base-check (4) code a web test failed
web / react-apps-base-check (2) code a web test failed
web / react-apps-base-check (1) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs agent-pane-background-tasks.test.ts the summary card lists the chat's background tasks: running ones first, the finished folded: failed (job)
  • seen on other PRs agent-pane-chat-unavailable.test.ts loading never shows the unavailable text: a slow attach, then a machine still connecting: failed (job)
  • seen on other PRs agent-pane-chat-unavailable.test.ts a chat whose machine goes offline names it, says when it was last seen, and Reconnect opens it: failed (job)
  • seen on other PRs agent-pane-hairline-focus.test.ts composer at 1x: focus is the resting hairline a step brighter, no ring: failed (job)
  • seen on other PRs agent-pane-hairline-focus.test.ts newtab at 1x: focus is the resting hairline a step brighter, no ring: failed (job)
  • seen on other PRs agent-pane-hairline-focus.test.ts composer at 2x: focus is the resting hairline a step brighter, no ring: failed (job)
  • seen on other PRs agent-pane-hairline-focus.test.ts newtab at 2x: focus is the resting hairline a step brighter, no ring: failed (job)
  • seen on other PRs agent-pane-hairline-focus.test.ts under Increase Contrast a focused edge keeps the resting edge, never a dimmer one: failed (job)
  • seen on other PRs accent-glass-invariants.test.ts no orange or system accent and no opaque glass on the gallery stages: failed (job)
  • seen on other PRs agent-pane-agents-pill.test.ts by default the running agents sit in the tray above the composer, not in the transcript: failed (job)
  • ... 22 more in the job logs
Matched log lines
web / react-apps-base-check (3): (fail) the summary card lists the chat's background tasks: running ones first, the finished folded [1029.41ms]
web / react-apps-base-check (4): (fail) no orange or system accent and no opaque glass on the gallery stages [512224.26ms]
web / react-apps-base-check (2): (fail) chromium > the gutter beside every part of the stack scrolls the transcript, and the part keeps the pointer [8851.05ms]
web / react-apps-base-check (1): (fail) only page.css imports the page's sheets [20.31ms]

Not re-run automatically: web / react-apps-base-check (3), web / react-apps-base-check (4), web / react-apps-base-check (2), web / react-apps-base-check (1), web / react-apps-check are not machine failures.

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.

red: web / Web status; base red: the same failure on the base af913f8; does not block
red: web / react-apps-base-check (1); no finished base run on af913f8 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (2); no finished base run on af913f8 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (3); no finished base run on af913f8 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (4); no finished base run on af913f8 to compare; do not merge until green; see lane-rules
red: web / react-apps-check; base red: the same failure on the base af913f8; does not block

Gallery before/after for f7afb1c: 16 states rendered, 0 images differ, 1334 more touched states not rendered. Images are in the run's artifact, not on this public PR.

gh run download 40661461612 -R manaflow-ai/cmux -n gallery-advisory-26551-f7afb1c8d9fb99ed9e2c0102ad33b3b81f0c3665 (then read gallery-review.json)

States
State Theme Status Diff Picked by
agent-pane.add-project-panel/environment Apple System Colors Light unchanged 0% own styles.css
agent-pane.add-project-panel/environment Apple System Colors unchanged 0% own styles.css
agent-pane.add-project-panel/sources Apple System Colors Light unchanged 0% own styles.css
agent-pane.add-project-panel/sources Apple System Colors unchanged 0% own styles.css
agent-pane.add-project-panel/directory Apple System Colors Light unchanged 0% own styles.css
agent-pane.add-project-panel/directory Apple System Colors unchanged 0% own styles.css
agent-pane.add-project-panel/keyboard Apple System Colors Light unchanged 0% own styles.css
agent-pane.add-project-panel/keyboard Apple System Colors unchanged 0% own styles.css
agent-pane.changes-file-menu/closed Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-file-menu/closed Apple System Colors unchanged 0% own styles.css
agent-pane.changes-file-menu/open Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-file-menu/open Apple System Colors unchanged 0% own styles.css
agent-pane.changes-file-menu/keyboard Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-file-menu/keyboard Apple System Colors unchanged 0% own styles.css
agent-pane.changes-git-actions/toolbar Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-git-actions/toolbar Apple System Colors unchanged 0% own styles.css
agent-pane.changes-git-actions/commit-form Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-git-actions/commit-form Apple System Colors unchanged 0% own styles.css
agent-pane.changes-git-actions/include-new Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-git-actions/include-new Apple System Colors unchanged 0% own styles.css
agent-pane.changes-git-actions/keyboard Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-git-actions/keyboard Apple System Colors unchanged 0% own styles.css
agent-pane.changes-git-actions/busy Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-git-actions/busy Apple System Colors unchanged 0% own styles.css
agent-pane.changes-git-actions/push-refused Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-git-actions/push-refused Apple System Colors unchanged 0% own styles.css
agent-pane.changes-options-menu/closed Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-options-menu/closed Apple System Colors unchanged 0% own styles.css
agent-pane.changes-options-menu/open Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-options-menu/open Apple System Colors unchanged 0% own styles.css
agent-pane.changes-options-menu/keyboard Apple System Colors Light unchanged 0% own styles.css
agent-pane.changes-options-menu/keyboard Apple System Colors unchanged 0% own styles.css

Pick other states with a Gallery: entry.id, entry.id/variant line in the PR body.

@blacksmith-sh

blacksmith-sh Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Found 4 test failures on Blacksmith runners:

Failures

Test View Logs
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build/
build_only must be a conjunctive exclusion on the helper, signing, and publication jobs
, and must not gate the unsigned app build
View Logs
nightly.yml must derive the embedded key and sign every appcast through the helper/
nightly.yml must derive the embedded key and sign every appcast through the helper
View Logs
test_the_nightly_is_covered (main.NightlyStepCoverageTests.test_the_nightly_is_cove
red)/
test_the_nightly_is_covered (main.NightlyStepCoverageTests.test_the_nightly_is_cove
red)
View Logs
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)/
test_the_repository_highlights_validate (main.DigestTests.test_the_repository_highl
ights_validate)
View Logs

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra high, next-review): BLOCK at 932c79d

  • [P2] webviews/src/agent-session/acpmux/newtab/NewTabScreen.tsx:576 — locationInFooter can be true when the optional chips prop is absent. In Claude/plain-footer mode on Minimal and other non-default, non-Cards templates, this hides .nt-above, while the footer also stays unrendered because split is false. The folder/computer controls disappear, preventing project selection. Require split in locationInFooter, or render the location footer independently.

@cursor

cursor Bot commented Oct 28, 2026

Copy link
Copy Markdown

Bugbot needs on-demand usage enabled

Bugbot uses usage-based billing for this team and requires on-demand usage to be enabled.

A team admin can enable on-demand usage in the Cursor dashboard.

@teamleaderleo
teamleaderleo merged commit 39e2456 into feat-cmux-next Oct 28, 2026
157 of 164 checks passed
@teamleaderleo
teamleaderleo deleted the lane/nx-picker-placement branch October 28, 2026 09:23
lawrencecchen added a commit that referenced this pull request Oct 28, 2026
…ooter row

#26551 put the folder strip in the footer whenever the plain footer and the
Claude look were on, but the footer row only renders with chips. A New Tab
without chips lost its project strip (new-tab-minimal-default, new-tab-stage-layout).

Tests: new-tab-ask-model gives the global scope the ResizeObserver the
always-mounted footer row now uses; new-tab-minimal-default keeps the
headline slot that new-tab-headline-place requires, and matches the folder
option label of #25316.
lawrencecchen added a commit that referenced this pull request Oct 28, 2026
… as in the app

#26126 (c22ebf6, 2026-10-27) added styles.css and diffTokens.css imports to
acpmux/main.tsx. The app's bundle drops those imports and ships each sheet once
in dev.tsx's order, but the gallery inserted them as second copies after its
combined pane sheet, so styles.css's base rules outranked every later sheet in
every agent-pane stage: the quiet row took .acpmux-composer-bar's 10 px
padding and 48 px height back. composer-side-inset failed all 68 cases on it.
The combined sheet now moves after those copies, so the gallery cascade is the
app's again.

Three values were tuned in that broken cascade; set them for the app's:
- the quiet row's mode chip: margin-inline-start 5px (was -5px,
  1ffab54), so its shield centers 22 px in, under the + glyph;
- the context ring: margin-inline-end 11px, its glyph under the mic's;
- Codex's look dots over the box: bottom 44px (was 64px, #26551), the row's
  28 px plus its 8 px margins, so they no longer cover the prompt's actions.

composer-side-inset follows the later intent: the box spans the column, the row
adds no padding, and its outer controls sit on the + and mic glyph columns
(composer-alignment-centers, 2026-10-27) rather than on the box's very edge;
the Classic page's row ends on its own footer bar's edge (#26551).
@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

lawrencecchen added a commit that referenced this pull request Oct 28, 2026
… stays in the box's row

composer-permission-pill (#25124) never ran green (its PR notes the browser
test did not execute):
- agent-pane.composer-look's started chat reported no modes, and a started
  chat with none shows no mode chip (#24169/#24517), so the test waited 30 s
  for a capsule that never drew. The fixture now reports Claude Code's modes.
- #26551 moved the chips into the quiet row under the box in both looks, but
  the Codex 16 px gap after the + glyph still matched that row
  (.acpmux-composer-bar is also the foot's class) and pushed the mode 3 px off
  its column. It is now scoped to the box's own row (and New Tab's pickers).
- The test checks the shared capsule (28 px, 8 px insets, full radius, steady
  on hover) in both looks, and the shield under the + glyph in Claude's, which
  composer-alignment-centers pins; no test pins Codex's + column yet.
teamleaderleo added a commit that referenced this pull request Oct 31, 2026
…28901)

* test(composer): pin Codex controls inside one box row

Agent-Session: https://cmux.com/deeplink/agent?id=aid-54f42482795c9f39329b

* fix(composer): restore Codex controls inside its box

Codex's look puts +, the mode, the context ring, the model, the mic and
Send in one row inside the box again, with the look dots in that row's
empty middle. Claude's quiet row is unchanged. Takes back #26551 for
Codex only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* fix(new-tab): keep Codex's controls in the box row on New Tab

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* test(new-tab): Codex's look keeps its chips in the box row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* fix(composer): Codex look dots stay clear of the row's controls; tests follow the in-box row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* fix(composer): Codex's in-box row takes the width steps with the plain footer

The plain footer's infinite fit width and CSS guards were meant for the
quiet row; key them on .acpmux-composer-foot so Codex's box row (and New
Tab's) collapse labels in narrow panes. Review of #28901.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* test(composer): the width-step guard skips only the plain quiet row

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* fix(composer): Codex row stays clickable in the floating dock; New Tab's Codex row steps its labels

Review of #28901: the floating dock's per-part pointer rule outranked the
dots host's pointer-events: none, and New Tab's Codex row had no row fit.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* fix(composer): Codex look dots host takes no height (design tokens)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* style(webviews): format the composer look tests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

* fix(new-tab): Codex row's model keeps its short and family names visible

Review of #28901: .acpmux-model-short and the fit-part display rules were
scoped to .acpmux-composer-bar, so New Tab's Codex row showed a blank model
between 370 and 440px.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-d750cf10922c785efa64

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>

This branch was previously deployed

1 inactive deployment
ci-routing-agent — f7afb1c8 Deployed Oct 28, 2026 by teamleaderleo via wait for same-key tree publisher #70974
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

risk:normal Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant