Skip to content

feat(cmux-next): migrate composer menus to native popups - #27144

Draft
teamleaderleo wants to merge 81 commits into
feat-cmux-nextfrom
native-composer-menu-consumers
Draft

teamleaderleo wants to merge 81 commits into
feat-cmux-nextfrom
native-composer-menu-consumers

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 29, 2026 •

Copy link
Copy Markdown
Collaborator

Routes composer mode, effort, Fast, options, Plan/Build, slash, and @ suggestions through the native popup protocol. Each consumer sends generated rows and consumes typed search, highlight, pick, change, and dismiss events; production DOM menu rows are removed.

This seam preserves existing mode/config/action IDs, labels, optimistic refusal handling, selection semantics, and composer caret edits. It depends on native popup foundation PR #27142 and overlaps model-picker consumer PR #27140; cherry-pick after those land and resolve only ComposerPickers consumer hunks. No QuickModelMenu or ModelPicker implementation is included.

Validation:

  • git diff --check
  • Prettier parser check on all changed consumer files
  • Typecheck unavailable in this lane (vp is not installed)

HOLD: land after #27142 and #27140 are integrated; then run native transport roundtrip, stale-revision, no-production-DOM, and real-app light/dark checks.

Agent session: agent session


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


Summary by cubic

Routes composer mode, effort, Fast, options, Plan/Build, slash, and @ suggestion menus, plus the shared Combobox, ContextMenu, Menu, Popover, and Select primitives, through the native popup protocol instead of mounting production DOM rows. Web code sends generated rows and consumes search, highlight, pick, change, submit, and dismiss events over a single popup identity with monotonically increasing revisions.

This PR also includes the popup foundation: a JSON-schema wire contract with a generator for the TypeScript and Swift Codable types, and an AppKit DeclarativePopupHost that renders the glass panels, search fields, named-stop sliders, editable controls, and side-by-side submenus while preserving keyboard focus and committed IME text across updates. Permission mode glyphs are added as native icons.

Preserves existing mode/config/action IDs, labels, optimistic refusal handling, selection semantics, and composer caret edits. HOLD: depends on native popup foundation PR #27142 and overlaps model-picker consumer PR #27140; cherry-pick after those land and resolve only ComposerPickers consumer hunks. No QuickModelMenu or ModelPicker implementation is included.

Written for commit 2a3c69c. Summary will update on new commits.

View guided diff Turn on auto-fix

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-3c5rlh 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 29, 2026
Agent-Session: $(agent-identity session 2>/dev/null || true)
Native popup rows use the shared Glass.makeOverlayPanel material, preserve Reduce Transparency, and keep popup identity and revision bound across native events.

Agent-Session: https://cmux.com/deeplink/agent?id=aid-c71c74308c1f7f21a180
@github-actions

Copy link
Copy Markdown
Contributor

Default changes

This pull request changes 1 default at 2a3c69c5e7cb (what everyone gets without configuring anything):

  • tunable-source.CmuxNextDesign/Overlay/NativePopupModel+Validation.swift:validate: (none) -> "f98d33770a0b7d0610dca09dcd557ef7c5dd6bca57e98fe320e87e4dadb032bb"

Needs a review. It passes with an independent review receipt on this commit: a comment or review whose first line is Review (<reviewer>): SHIP at 2a3c69c5e7cb525dcee8fd7fad96b535d62769a4, from a member, not a self-review (the newest verdict naming the head decides; a later BLOCK beats an earlier SHIP), or with an approving review on this commit from @lawrencecchen or @austinywang (the call owners in .github/defaults-call-owners.json, never the author). A receipt posted as a review re-runs this check; after a plain comment, re-run it. The needs a call label alone does not pass, and a new push needs a new receipt.

Regenerate the snapshot with python3 scripts/ci/defaults_guard.py snapshot.

@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

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

Unclear: web / react-apps-base-check (3) failed: no known signature; failed step: Run base reds and compare.

CI failed on 2a3c69c5e7 (run 40928108919 attempt 1): 3 code, 2 unknown.

Job Verdict Why
web / react-apps-base-check (3) unknown no known signature; failed step: Run base reds and compare
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 MarkdownMath.test.tsx keeps shell command dollar signs as plain text without dropping content: failed (job)
  • seen on other PRs queuedMessages.test.ts each agent message is a received-card row, in the queue's order, with its promptId: failed (job)
  • seen on other PRs chiefLook.test.tsx search renders Bubble Style in the Look card: failed (job)
  • seen on other PRs themePane.test.tsx the Theme page draws each theme key once, in one card, with no second App Theme group: failed (job)
  • seen on other PRs agent-pane-pending-steer.test.tsx Send now on a waiting steer asks queue_edit send_now for its promptId, and goes once it is read: failed (job)
  • seen on other PRs bare-ref-repo.test.tsx an agent's message: its own address names the repository of its bare #N: failed (job)
  • seen on other PRs classic-new-tab-trust.test.tsx a start refused after a while keeps the prompt ahead of what was typed in the composer meanwhile: failed (job)
  • seen on other PRs clickable-cursor.test.ts no stylesheet sets the arrow or auto on a clickable element: failed (job)
  • seen on other PRs glyph-alignment.test.ts glyphs use shared row geometry in light and dark: failed (job)
  • seen on other PRs chat-open-long.test.ts a 700-turn chat opened cold on a busy daemon shows its rows with the attach, never an empty page: failed (job)
  • ... 14 more in the job logs
Matched log lines
web / react-apps-base-check (4): (fail) keeps shell command dollar signs as plain text without dropping content [6.30ms]
web / react-apps-base-check (2): (fail) glyphs use shared row geometry in light and dark [22342.68ms]
web / react-apps-base-check (1): (fail) no description line on any Settings page is over 60 characters, in any language [25597.55ms]

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: cmux-next checks (god files, concurrency, crash safety, l10n); NEW: red check: Package dependency lists sorted is not red on the base 89b99d5; do not merge until green; see lane-rules
red: web / Web status; base red: the same failure on the base 89b99d5; does not block
red: web / react-apps-base-check (1); no finished base run on 89b99d5 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (2); no finished base run on 89b99d5 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (3); no finished base run on 89b99d5 to compare; do not merge until green; see lane-rules
red: web / react-apps-base-check (4); no finished base run on 89b99d5 to compare; do not merge until green; see lane-rules
red: web / react-apps-check; base red: the same failure on the base 89b99d5; does not block

@blacksmith-sh

blacksmith-sh Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Found 48 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp5j0sfo7i/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmpgb1fplk_/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
src/agent-session/acpmux/conversation/MarkdownMath.test.tsx/MarkdownMath.test.tsx View Logs
src/agent-session/acpmux/conversation/MarkdownMath.test.tsx/MarkdownMath.test.tsx View Logs
src/agent-session/acpmux/conversation/queuedMessages.test.ts/queuedMessages.test View Logs
src/agent-session/acpmux/conversation/queuedMessages.test.ts/queuedMessages.test View Logs

...and 38 more test failures. View all on Blacksmith

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

Copy link
Copy Markdown
Collaborator Author

W2-09 follow-up for the native composer-popup owner — tested bounded-row experiment

The W2-09 independent research prototype is in HQ draft PR #5954, at exact head 6d990f582951573c5aa27fdb5994ea846f6efa6e. It contains a real interactive synthetic HTML composer, a pure result-viewport/selection helper, seven passing Node tests, and a passing Chromium 144 DOM check (5,000 advertised skills, <=23 mounted option rows, keyboard 39→40→last→wrap, wheel, Ctrl-J/K, IME key handling, Escape draft restoration, narrow/wide widths, aria-activedescendant and aria-posinset/setsize). This tests the prototype, not the native host or cmux app.

Still present on refreshed feat-cmux-next@3154610eef3b56760363456b9c2dd3f44ae8763c: slashCommands.ts:78-92 sorts the whole match set; Composer.tsx:2518 mounts one option per match. Merged #30230 limits the + menu itself; its “Commands and skills…” handoff still reaches this eager slash list. Native popup foundation #27142 is now merged, while this composer migration remains draft/HOLD.

Specific owner-review question: When this PR migrates / suggestions, can the native popup receive only the visible window with a stable global logical index, total count and selected row identity, including across a 39→40 crossing and a wheel jump? The 31px slash row and 296px popup yield <=23 mounted rows with six overscan rows. If the native host already bounds its row model while retaining full keyboard/AX and filter semantics, this experiment's slice can be retired. If it sends 5,000 row descriptors on every edit or retains an eagerly mounted HTML fallback, that is the integration gap to close.

Boundary: Please treat #5954 as tested research/test fixtures, not a patch to cherry-pick without adapting the native keyboard and AX protocol. Exact next acceptance: a real #27144 build with 5,000 skills, controlled row-count assertion at both DOM/native surfaces, Arrow/Ctrl-J/K/Tab/Return/IME, Escape restoring the + draft, VoiceOver active item and input→visible-menu p95/p99. No production code was changed or pushed to your branch, and no coordinator dispatch is requested.

Copy link
Copy Markdown
Collaborator Author

W2-09 integration heads-up (exact current production diff): cmux #31293 is now the independent draft/HOLD bounded-slash-view implementation on feat-cmux-next. It adds slashViewport.ts with full-index/window/scroll logic and updates the actual Composer.tsx HTML slash picker to mount a small row window for >40 matches; its unit tests cover 5,000 options. I left your #27144 native-popup consumer branch untouched. When your native slash menu replaces the DOM renderer, please reuse or evaluate this bounded logical index contract at the host boundary; sending 5,000 native popup rows eagerly would reproduce the issue even after removing DOM rows. The existing native-popup foundation #27142 is merged. Full native roundtrip, AX, browser and visual checks for the integration remain open; no merge requested. The HQ prototype #5954 was closed as misplaced/superseded by this cmux PR.

This branch was previously deployed

1 inactive deployment
ci-routing-agent — 2a3c69c5 Deployed Oct 29, 2026 by teamleaderleo via cmux-tui tree preflight #77688
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